spring framework入门(6):java中的动态代理(jdk和cglib)

2024-05-15 18:48

本文主要是介绍spring framework入门(6):java中的动态代理(jdk和cglib),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参照:https://www.cnblogs.com/kuotian/p/8849414.html

试验代码:https://download.csdn.net/download/u010476739/11430244

试验环境:

工具:eclipse maven cglib-3.2.12

首先列出java中代理底层的实现方式:

1)静态代理

一个类一个代理,重复代码仍然较多,复用度低。事先写好代理对象类,在程序发布前就已经存在了,调用真实业务方法。

2)jdk动态代理

应用程序发布后,通过动态创建代理对象。通过反射进行invoke回调,要求业务类必须有接口,没有接口无法生成代理对象

3)cglib动态代理

不要求业务类必须有接口,有实现类即可。底层采用asm字节码生成框架生成代理类的字节码,它创建慢,但一旦创建要比jdk方式快。cglib使用继承,因此父类最好不要有final属性,final阻止继承和多态。

一、静态代理

      其实这个就是java中的装饰者模式。

二、jdk动态代理

   2.1 首先定义业务类(注意要被代理的方法抽取到接口中)

Business.java

package jdkproxy;public interface Business {public String Add(int i, int j);
}

BusinessImpl.java

package jdkproxy;public class BusinessImpl implements Business {public String Add(int i, int j) {return String.valueOf(i + j);}
}

2.2 定义代理类

Logger.java

package jdkproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class Logger implements InvocationHandler{private Object targetObject;public Logger(Object targetObject) {this.targetObject=targetObject;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object obj=null;try {System.out.println("jdk 调用了实例:"+proxy.getClass().toGenericString()+",method:"+method.toGenericString()+".");//由目标对象调用实际的功能方法obj=method.invoke(targetObject, args);System.out.println("jdk 调用完毕!");}catch(Exception e) {e.printStackTrace();}return obj;}}

2.3 测试调用

public static void main(String[] args) {/** jdk动态代理(基于接口实现): * 1.业务类只能通过接口被代理,所以被代理的方法要抽取到接口中去定义 * 2.代理类必须实现InvocationHandler接口* 3.使用的时候根据业务类实例对象创建出代理对象,然后用接口调用*/jdkproxy.Business targetObject = new jdkproxy.BusinessImpl();jdkproxy.Business busi = (jdkproxy.Business) Proxy.newProxyInstance(jdkproxy.BusinessImpl.class.getClassLoader(),jdkproxy.BusinessImpl.class.getInterfaces(), new jdkproxy.Logger(targetObject));System.out.println(busi.Add(1, 2));
}

输出:

三、cglib动态代理

3.1 添加cglib依赖

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.jackletter</groupId><artifactId>jdkproxy</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><!-- https://mvnrepository.com/artifact/cglib/cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.12</version></dependency></dependencies>
</project>

3.2 首先定义业务类(不用接口)

Business.java

package cdlibproxy;public class Business {public String Add(int i, int j) {return String.valueOf(i + j);}
}

3.3 定义代理类

Logger.java

package cdlibproxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class Logger implements MethodInterceptor {private Object targetObject;public Logger(Object targetObject) {this.targetObject=targetObject;}public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {Object res=null;try {System.out.println("cglib 调用了实例:"+obj.getClass().toGenericString()+",method:"+method.toGenericString()+".");//由目标对象调用实际的功能方法res=method.invoke(targetObject, args);System.out.println("cglib 调用完毕!");}catch(Exception e) {e.printStackTrace();}return res;}
}

3.4 测试调用

public static void main(String[] args) {/** cglib动态代理(基于集成实现):* 1.业务类不受任何影响(没有强制抽取接口)* 2.代理类必须实现MethodInterceptor接口* 3.使用的时候根据业务类实例对象创建出代理对象,然后用直接调用*/cdlibproxy.Business busi2 = new cdlibproxy.Business();Object obj = null;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(busi2.getClass());enhancer.setCallback(new cdlibproxy.Logger(busi2));busi2 = (cdlibproxy.Business) enhancer.create();System.out.println(busi2.Add(2, 3));
}

输出:

这篇关于spring framework入门(6):java中的动态代理(jdk和cglib)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992622

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav