动态代理 JDK和CGLib的区别?

JDK和CGLib动态代理分析

自Java1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例。后来这项技术被用到了Spring的很多地方。JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler。其中,InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑(如:我们在方法执行前后打印的日志,本文只是为了演示,实际的应用一般不会只是简单的打印日志的),并通过反射机制调用目标类的代码,动态地将横切逻辑和业务逻辑编织在一起。

JDK动态代理地话,他有一个限制,就是它只能为接口创建代理实例,而对于没有通过接口定义业务方法地类,如何创建动态代理实例?答案就是CGLib。

CGLib(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理,在子类中才哦那个方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。

ASM是什么:
ASM是一个JAVA字节码分析、创建和修改的开源应用框架。它可以动态生成二进制格式的stub类或其他代理类,或者在类被Java虚拟机装入内存之前,动态修改类。在ASM中提供了诸多的API用于对类的内容进行字节码操作的方法。与传统的BCEL和SERL不同,在ASM中提供了更为优雅和灵活的操作字节码的方式。ASM相当小巧,并且它有更高的执行效率,是BCEL的7倍,SERP的11倍以上。目前ASM已被广泛的开源应用框架所适用,例如:Spring、Hibernate等

JDK和CGLib动态代理区别
  1. JDK动态代理具体实现原理
  • 通过实现InvocationHandler接口创建自己的调用处理器;
  • 通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理;
  • 通过发射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入;
  • JDK动态代理是面向接口的代理模式,如果被代理目标没有接口那么Spring也无能为力,Spring通过Java的发射机制生产被代理接口的新的匿名实现类,重写了其中AOP的增强方法;
  1. CGLib动态代理
  • 利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
  1. 两者对比
  • JDK动态代理是面向接口的;
  • CGLib动态代理是通过字节码底层继承要代理类来实现,因此如果代理类被final关键字所修饰,会失败
  1. 使用注意
  • 如果要被代理的对象是个实现类,那么Spring会使用JDK动态代理来完成操作(Spring默认采用JDK动态代理实现机制)
  • 如果要被代理的对象不是个实现类,那么Spring会强制使用CGLib来实现动态代理。
JDK和CGLib动态代理性能对比
  • 在1.6和1.7的时候,JDK动态代理的速度要比CGLib动态代理的速度要慢,但是并没有教科书上的10倍差距;
  • 在JDK1.8的时候,JDK动态代理的速度已经比CGLib动态代理的速度快很多了,但是JDK动态代理和CGLib动态代理的适用场景还是不一样的。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值