Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
JDK 动态代理只能对实现了接口的类生成代理,而不能针对类.
JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
InvocationHandler 是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类 的代码,动态将横切逻辑和业务逻辑编制在一起。
Proxy 利用 InvocationHandler 动态创建 一个符合某一接口的实例,生成目标类的代理对象。
CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)CGLib 全称为 CodeGeneration Library,是一个强大的高性能,高质量的代码生成类库, 可以在运行期扩展Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新class。
CGLIB和 JDK 动态代理相比较:
JDK 创建代理有一个限制,就是只能为接口创建代理实例, 而对于没有通过接口定义业务方法的类,则可以通过CGLib 创建动态代理。(一个是只能在接口内,另一个在类内)
Spring 在选择用 JDK 还是 CGLiB 的依据:
(1)当 Bean 实现接口时,Spring 就会用 JDK 的动态代理
(2)当 Bean 没有实现接口时,Spring 使用 CGlib 是实现
(3)可以强制使用 CGlib(在 spring 配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>
CGlib 比 比 JDK 快??
(1)使用 CGLib 实现动态代理,CGLib 底层采用 ASM 字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib 不能对声明为 final 的方法进行代理,因为 CGLib 原理是动态生成被代理类的子类。
(2)在对 JDK 动态代理与 CGlib 动态代理的代码实验中看,1W 次执行下,JDK7 及 8 的动态代理性能比 CGlib 要好 20%左右。