ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JDK和CGLib动态代理的实现和区别

2021-06-16 16:34:54  阅读:124  来源: 互联网

标签:JDK Spring 代理 接口 CGLib 动态


JDK和CGLib动态代理实现

动态代理在Java中有着广泛的应用,如Spring AOP,Hibernate数据查询、测试框架的后端mock、RPC,Java注解对象获取等。动态代理的代理关系是在运行时期确定的。接下来主要阐述两种动态代理的区别。

JDK和CGLib动态代理分析

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

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

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

 

JDK和CGLib动态代理区别

1、JDK动态代理具体实现原理:

通过实现InvocationHandler接口创建自己的调用处理器;

通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理;

通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;

通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入;

JDK动态代理是面向接口的代理模式,如果被代理目标没有接口那么Spring也无能为力,Spring通过Java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的增强方法。

 

2、CGLib动态代理:

利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

3、两者对比:

JDK动态代理是面向接口的。

CGLib动态代理是通过字节码底层继承要代理类来实现,因此如果被代理类被final关键字所修饰,会失败。

4、使用注意:

如果要被代理的对象是个实现类,那么Spring会使用JDK动态代理来完成操作(Spirng默认采用JDK动态代理实现机制);

如果要被代理的对象不是个实现类那么,Spring会强制使用CGLib来实现动态代理。

JDK和CGLib动态代理性能对比

关于两者之间的性能的话,网上有人对于不通版本的jdk进行测试,经过多次试验,测试结果大致是这样的,在1.6和1.7的时候,JDK动态代理的速度要比CGLib动态代理的速度要慢,但是并没有教科书上的10倍差距,在JDK1.8的时候,JDK动态代理的速度已经比CGLib动态代理的速度快很多了,但是JDK动态代理和CGLIB动态代理的适用场景还是不一样的哈!

结论:

        综上,JDK是基于接口而CGLib是基于继承

1)、JDK和CGLib的区别

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类
  • CGLib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

2)、Spring在选择用JDK还是CGLib的依据

  • 当Bean实现接口时,Spring就会用JDK的动态代理
  • 当Bean没有实现接口时,Spring使用CGLib来实现
  • 可以强制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)

3)、JDK和CGLib的性能对比

  • 使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
  • 在JDK1.6、JDK1.7、JDK1.8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLib代理效率,只有当进行大量调用的时候,JDK1.6和JDK1.7比CGLib代理效率低一点,但是到JDK1.8的时候,JDK代理效率高于CGLib代理

标签:JDK,Spring,代理,接口,CGLib,动态
来源: https://www.cnblogs.com/doubleflower/p/14889891.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有