一、cglib和jdk动态代理的区别
- jdk动态代理实现了被代理对象的接口,cglib是继承了被代理的对象【通过字节码技术创建这个类的子类,实现动态代理】
- 都是在运行期间,jdk是直接写class字节码,cglib使用asm框架写字节码,实现更复杂
- java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法时用InvokeHandler,cglib是通过继承要被代理类的机制
- jdk调用代理方法,通过反射机制,cglib通过fastclass机制直接调用方法,这方面cglib执行效率更高
二、jdk动态代理和cglib要求
1)jdk动态代理
- 动态代理类实现InvocationHandler接口【必须】
- 被代理的类必须要实现一个接口
- 使用Proxy.newProxyInstance产生代理对象
2)cglib要求
- jdk动态代理类库中已有,而cglib必须加入第三方依赖(cglib、asm)
三、速率上的区别
- 对于创建实例:jdk更快,相比之下cglib创建实例的过程比较繁琐
- 对于方法执行效率:cglib更快,基于asm操作字节码技术和fastclass机制(通过索引调用方法),比基于反射的jdk动态代理来的快。
四、cglib的局限性(缺点)
- cglib无法代理final修饰的类和final修饰的方法
原因:
- final类不能被继承、没有子类、final类中修饰的方法默认是final
- final方法不能被子类的方法覆盖
- 而cglib的底层的代理类恰好就是通过继承要代理的目标类来实现种种操作。
五、Spring代理选择
- 当bean实现接口时,spring使用jdk动态代理
- 当bean没实现接口,spring使用cglib
- 可以通过配置强制走cglib,<aop:aspectj-autoproxy proxy-target-class="true"/>,如果是基于注解的方式,比如说springboot项目的启动类,可以使用@EnableAspectJAutoProxy(proxyTargetClass=true)注解来强制使用cglib
评论区