觉得可以的话点个关注转个发呗,陆续奉上干货~~~~

前文我们讲解了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动态代理原理示例解析相关推荐

  1. Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理

    文章目录 什么是代理模式 代理模式应用场景 代理的分类 静态代理 什么是静态代理 深入解析静态代理 小结 动态代理 什么是动态代理 JDK动态代理 原理和实现方式 代码实现 优缺点 Cglib动态代理 ...

  2. 静态代理,cglib动态代理,jdk动态代理区别以及流程详解

    1.静态代理 静态代理使用的是代理设计模式,不讲高大上的思想,我们直接实战 这是动物接口,其中有一个吃饭方法 这是其中的一只动物,实现了动物接口,覆盖了吃饭方法 现在我们思考,我想要给猫找一个代理,希 ...

  3. java jdk动态代理 cglib动态代理demo

    最近在研究java动态代理这块,以前也看了很多次java动态代理,感觉一直不是怎么明白,这两天看了看又明白了些,现给出我参考网上写的一个demo jdk动态代理实现: View Code import ...

  4. 一文理解JDK静态代理、JDK动态代理、Cglib动态代理

    代理模式 通过代理来访问真实的对象,而不是直接去访问真正干活的对象,比如二房东租房,二房是代理者,而一房东才是真正的房东:或者说生活中的中介.Spring中的AOP就是动态代理 适用场景 需要动态修改 ...

  5. Java两种动态代理JDK动态代理和CGLIB动态代理

    目录 代理模式 JDK动态代理 cglib动态代理 测试 代理模式 代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式.为了对外开放协议,B往往实现了一个 ...

  6. 代理模式(Java版)-静态代理、JDK动态代理和CGLib动态代理

    代理模式前传 前几天有个小朋友问到我代理模式,这个我拿手的嘛.废话不多说,直接开讲?这是不可能的. 一般呢,讲模式之前呢,礼貌上都要讲个前传.象我这种老了根本不怕没有故事祭奠的人,随手一个前传开始. ...

  7. 你必须会的 JDK 动态代理和 CGLIB 动态代理

    来自:ytao 我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性.通过从静态代理.JDK 动态代理.CGLIB 动 ...

  8. Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理

    Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理 代理模式 JDK动态代理 CGLIB动态代理 代理模式 代理模式是23种设计模式的一种,指一个对象A通过持有另一个对象B,可以具有B ...

  9. 利用代码分别实现jdk动态代理和cglib动态代理_面试之动态代理

    大家好!我是CSRobot,从今天开始,我将会发布一些技术文章,内容就是结合春招以来的面试所遇到的问题进行分享,首先会对知识点进行一个探讨和整理,在最后会给出一些面试题并作出解答,希望可以帮助到大家! ...

最新文章

  1. 电抗电路的串并联的转换
  2. ES使用org.elasticsearch.client.transport.NoNodeAvailableException: No node available 错误解决方法
  3. Linux2.6内核 -- 编码风格(3)
  4. Ruby种的特殊变量
  5. 和csm_CSM媒介研究首发短视频用户价值研究报告
  6. 关于C语言中递归的一点点小问题
  7. 邂逅StringIndexOutOfBoundsException
  8. C语言 底层IO readwrite
  9. 两个变量相乘_自动控制原理-信号流图与系统状态变量传递函数之间联系如此紧密...
  10. python编写学生管理系统设计感想-python案例----学生管理系统(实现学员的增删改查功能)...
  11. 生物信息学_测序技术(一)DNA测序
  12. 交叉报表制作--Smartbi报表工具一步完成
  13. FPGA学习记录 ACX720 Vivado
  14. 计算机自动化程序高 应用范围广是由于,计算机等级考试一级笔试模拟试题(三)及答案...
  15. Android打码函数,Android 图片编辑的原理与实现——涂鸦与马赛克
  16. python自动生成统计表_python处理Excel自动统计表
  17. matlab应力分析,MATLAB有限元分析与应用概述.ppt
  18. 计算机主机发出滴滴声音怎么办,电脑主机有滴滴声音是怎么回事?
  19. automotive industry is embracing change and agile transitioning
  20. java实现中国象棋1:界面的制作

热门文章

  1. 得到数组的最后一个数
  2. 音视频系列--哥伦布编码和H264片段sps解析宽高信息
  3. mysql sdo geometry_c#读写SDO_GEOMETRY字段
  4. E212:无法打开并写入文件
  5. 计算机等级培训计划书
  6. 关于STM32与GSM模块之间简单应用
  7. 碎碎念 2022.4.25
  8. 万能视频格式转换器是一款功能强大的全能视频格式转换软件,支持多种视频格式转换。万能视频转换器可以将R...
  9. Electron 学习
  10. android.content.res.Resources$NotFoundException Resource ID #0xfffffe6c