一、原理区别(版本一)
Java 动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler 来处理。
而 cglib 动态代理是利用 asm 开源包,对代理对象类的 class 文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP。
2、如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP。
3、如果目标对象没有实现了接口,必须采用 CGLIB 库,spring 会自动在 JDK 动态代理和 CGLIB 之间转换。
二、JDK 动态代理和 CGLIB 字节码生成的区别
1、JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。
2、CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法因为是继承,所以该类或方法最好不要声明成 final。
三、原理区别(版本二)
1、JDK动态代理
JDK 动态代理只提供接口的代理,不支持类的代理。核心 InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。
2、CGLIB 动态代理
如果代理类没有实现 InvocationHandler 接口,那么 SpringAOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
四、静态代理和动态代理区别
静态代理和动态代理区别在于生成 AOP 代理对象的时机不同,相对来说 AspectJ 的静态代理方式具有更好的性能,但是 AspectJ 需要特定的编译器进行处理,而 SpringAOP 则无需特定的编译器处理。
五、补充说明
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最终生成的代理实例;method 是被代理目标实例的某个具体方法;args 是被代理目标实例某个方法的具体入参,在方法反射调用时使用。
六、区别(版本三)
1、JDK 动态代理
JDK 动态代理是不需要依赖第三方的库,只要 JDK 环境 就可以进行代理,它有几个要求
1. 实现 InvocationHandler
2. 使用 Proxy.newProxyInstance 产生代理对象
3. 被代理的对象必须要实现接口
使用 JDK 动态代理,目标类必须实现的某个接口,如果某个类没有实现接口,则不能生成代理对象
2、CGLIB 动态代理
CGLIB 必须依赖于 CGLIB 的类库,CGLIB 原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为 final 类型。
针对接口编程的环境下推荐使用 JDK 的代理。从执行效率上看,CGLIB 动态代理效率较高。在 Hibernate 中的拦截器其实现考虑到不需要其他接口的条件 Hibernate 中的相关代理采用的是 CGLIB 来执行。
标签:JDK,代理,接口,生成,CGLIB,动态 From: https://www.cnblogs.com/Rover20230226/p/17469872.html