动态代理-cglib和jdk动态代理

一、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

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.fengpt.cn/archives/动态代理-cglib和jdk动态代理