动态代理——CGLIB动态代理原理示例解析
觉得可以的话点个关注,转个发呗,陆续奉上干货~~~~
前文我们讲解了JDK动态代理的原理(动态代理——JDK动态代理原理),今天我们来看看CGLIB动态代理是如何实现,最后我们总结下JDK动态代理和CGLIB动态代理的区别~~
先看下测试的源码:
输出:
inceptor-1---before invoke method: sayHello
i am cglib
inceptor-1---after invoke method: sayHello
我们看下CGLIB生成的代理类(精简之后):
通过注释我们可以观察到代理类以及代理对象的实现方式:
- 首先CGLIB使用ASM工具根据父类HelloServiceImpl及我们定义的方法拦截器MethodInterceptor生成代理CglibTest$HelloServiceImpl$$EnhancerByCGLIB$$69dcec54的字节码,然后将该字节码加载到虚拟机并根据静态代码块使用INIT方法初始化类中的类变量parentSayHelloMethod、sayHelloMethodProxy(及其他信息,截图中已省略其他信息,防干扰)
- 实例化代理类CglibTest$HelloServiceImpl$$EnhancerByCGLIB$$69dcec54的对象,记为代理对象A,并伴随着代理类中的成员属性methodInterceptor初始化为我们定义的MethodInterceptor对象,因为我们的代理类继承了HelloServiceImpl,因此可以强转(HelloServiceImpl)A
- 调用代理对象的sayHello方法:(HelloServiceImpl)A.sayHello(...)
- 结合上图,我们看到调用sayHello实际上调用了我们定义的MethodInterceptor的methodInterceptor方法
接下来我们关注红框中的方法:
methodProxy.invokeSuper(proxyObj, args); // 7、执行父类对应方法
methodProxy这个对象是在生成的代理类的INIT方法中进行初始化的(上去看下图):
sayHelloMethodProxy = MethodProxy.create(parentClass, proxyClass, "方法描述", "sayHello", "cglibSayHello");
我们看下create方法:
接下来看invokeSuper方法:
在这个方法中,init方法用来初始化fastClassInfo这个属性对象,最终调用的是fci.f2.invoke方法。根据名字我们推断fastClassInfo是快速的,应该是用来优化性能的一个东西,我们回顾JDK动态代理的实现方式时,我们在invoke方法中是根据method对象反射进行调用的,我们知道反射的性能相对较低,那么fastClassInfo这个对象是怎么优化的呢?
我们来看下init方法,为了说明init方法的意思,写了两个类(真实的这两个类也是CGLIB动态生成的,内部为每个方法描述生成了唯一的索引并使用switch表达式进行分支控制,本例为了简单说明是使用if语句根据方法名称进行判断,理解意思即可)
class HelloServiceImpl$$FastClass{public Object invoke(int index, HelloServiceImpl obj, Object[] args){if (index == "sayHello".hashCode()){return obj.sayHello((String)args[0]);}else {// ....其他方法}return null;}
}
class Proxy$$FastClass{public Object invoke(int index, ProxyClass proxy, Object[] args){if (index == "cglibSayHello".hashCode()){return proxy.cglibSayHello((String)args[0]);}else {// ....其他方法}return null;}
}
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1); // f1指向HelloServiceImpl$$FastClass的一个实例
fci.f2 = helper(ci, ci.c2); // f2指向Proxy$$FastClass的一个实例
fci.i1 = fci.f1.getIndex(sig1); // 生成父类sayHello方法的一个唯一索引
fci.i2 = fci.f2.getIndex(sig2); // 生成代理类cglibSayHello方法的一个唯一索引
fastClassInfo = fci;
createInfo = null;
完成上面的初始化后我们进入到这个方法的分析:
return fci.f2.invoke(fci.i2, obj, args);
f2指向Proxy$$FastClass实例(上面的注释),调用的就是proxy.cglibSayHello((String)args[0])这个方法,我们再回到最开始生成的代理类中,查看cglibSayHello方法,调用的是父类的sayHello方法:
final String cglibSayHello(String var1) {return super.sayHello(var1);
}
这样就形成了一个闭环~~~~
因此CGLIB在这一部分的优化就是用了判断的形式直接调用的对象的方法,付出的代价是多加载了几个类到虚拟机中,是一种空间换时间的一种思想;而JDK的方式是使用方法对象进行反射调用,节省了空间但降低了效率
总结JDK动态代理和CGLIB动态代理:(两种实现方式大体思路基本相同)
JDK动态代理:
- 需要目标类实现接口
- 生成的代理类是与目标类平级,实现了共同的接口
- 使用反射的方式进行最终方法的调用,性能较低
CGLIB动态代理:
- 不要求目标类实现接口
- 生成的代理类是目标类的子类
- final方法不会出现在代理类中
- 使用空间换时间的思想对最终的方法调用进行了优化,提升了运行时优化
把代码的意思用文字表述出来,一不小心就感觉有点乱,不知道大家能不能看懂~~~欢迎留言~~~
觉得可以的话点个关注,转个发呗,陆续奉上干货~~~~
动态代理——CGLIB动态代理原理示例解析相关推荐
- Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理
文章目录 什么是代理模式 代理模式应用场景 代理的分类 静态代理 什么是静态代理 深入解析静态代理 小结 动态代理 什么是动态代理 JDK动态代理 原理和实现方式 代码实现 优缺点 Cglib动态代理 ...
- 静态代理,cglib动态代理,jdk动态代理区别以及流程详解
1.静态代理 静态代理使用的是代理设计模式,不讲高大上的思想,我们直接实战 这是动物接口,其中有一个吃饭方法 这是其中的一只动物,实现了动物接口,覆盖了吃饭方法 现在我们思考,我想要给猫找一个代理,希 ...
- java jdk动态代理 cglib动态代理demo
最近在研究java动态代理这块,以前也看了很多次java动态代理,感觉一直不是怎么明白,这两天看了看又明白了些,现给出我参考网上写的一个demo jdk动态代理实现: View Code import ...
- 一文理解JDK静态代理、JDK动态代理、Cglib动态代理
代理模式 通过代理来访问真实的对象,而不是直接去访问真正干活的对象,比如二房东租房,二房是代理者,而一房东才是真正的房东:或者说生活中的中介.Spring中的AOP就是动态代理 适用场景 需要动态修改 ...
- Java两种动态代理JDK动态代理和CGLIB动态代理
目录 代理模式 JDK动态代理 cglib动态代理 测试 代理模式 代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式.为了对外开放协议,B往往实现了一个 ...
- 代理模式(Java版)-静态代理、JDK动态代理和CGLib动态代理
代理模式前传 前几天有个小朋友问到我代理模式,这个我拿手的嘛.废话不多说,直接开讲?这是不可能的. 一般呢,讲模式之前呢,礼貌上都要讲个前传.象我这种老了根本不怕没有故事祭奠的人,随手一个前传开始. ...
- 你必须会的 JDK 动态代理和 CGLIB 动态代理
来自:ytao 我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性.通过从静态代理.JDK 动态代理.CGLIB 动 ...
- Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理
Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理 代理模式 JDK动态代理 CGLIB动态代理 代理模式 代理模式是23种设计模式的一种,指一个对象A通过持有另一个对象B,可以具有B ...
- 利用代码分别实现jdk动态代理和cglib动态代理_面试之动态代理
大家好!我是CSRobot,从今天开始,我将会发布一些技术文章,内容就是结合春招以来的面试所遇到的问题进行分享,首先会对知识点进行一个探讨和整理,在最后会给出一些面试题并作出解答,希望可以帮助到大家! ...
最新文章
- 电抗电路的串并联的转换
- ES使用org.elasticsearch.client.transport.NoNodeAvailableException: No node available 错误解决方法
- Linux2.6内核 -- 编码风格(3)
- Ruby种的特殊变量
- 和csm_CSM媒介研究首发短视频用户价值研究报告
- 关于C语言中递归的一点点小问题
- 邂逅StringIndexOutOfBoundsException
- C语言 底层IO readwrite
- 两个变量相乘_自动控制原理-信号流图与系统状态变量传递函数之间联系如此紧密...
- python编写学生管理系统设计感想-python案例----学生管理系统(实现学员的增删改查功能)...
- 生物信息学_测序技术(一)DNA测序
- 交叉报表制作--Smartbi报表工具一步完成
- FPGA学习记录 ACX720 Vivado
- 计算机自动化程序高 应用范围广是由于,计算机等级考试一级笔试模拟试题(三)及答案...
- Android打码函数,Android 图片编辑的原理与实现——涂鸦与马赛克
- python自动生成统计表_python处理Excel自动统计表
- matlab应力分析,MATLAB有限元分析与应用概述.ppt
- 计算机主机发出滴滴声音怎么办,电脑主机有滴滴声音是怎么回事?
- automotive industry is embracing change and agile transitioning
- java实现中国象棋1:界面的制作
热门文章
- 得到数组的最后一个数
- 音视频系列--哥伦布编码和H264片段sps解析宽高信息
- mysql sdo geometry_c#读写SDO_GEOMETRY字段
- E212:无法打开并写入文件
- 计算机等级培训计划书
- 关于STM32与GSM模块之间简单应用
- 碎碎念 2022.4.25
- 万能视频格式转换器是一款功能强大的全能视频格式转换软件,支持多种视频格式转换。万能视频转换器可以将R...
- Electron 学习
- android.content.res.Resources$NotFoundException Resource ID #0xfffffe6c