jdk动态代理实例和cglib动态代理实例_CGLib 动态代理 原理解析
- JDK 动态代理实现与原理
首先来看一段CGLib代理的测试代码(MethodInterceptor的测试, 其他类型这里不做展开了). Util类的代码在后面给出的码云片段中
public
下面的输出结果除了测试动态代理生效结果外, 还将动态代理生成的类名也输出出来了. 这些类名信息, 在后面的分析中会用到.
Current Pid is:54801
co/wangming/cglib/methodinterceptor/MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
proxy start : class net.sf.cglib.proxy.MethodProxy: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
*****************CreateInfo***********************
Proxy Class: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$printHi$0$Proxy CreateInfo : class net.sf.cglib.proxy.MethodProxy$CreateInfo
CGLIB$printHi$0$Proxy CreateInfo c1: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A
CGLIB$printHi$0$Proxy CreateInfo c2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$equals$1$Proxy CreateInfo : class net.sf.cglib.proxy.MethodProxy$CreateInfo
CGLIB$equals$1$Proxy CreateInfo c1: class java.lang.Object
CGLIB$equals$1$Proxy CreateInfo c2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$toString$2$Proxy CreateInfo : class net.sf.cglib.proxy.MethodProxy$CreateInfo
CGLIB$toString$2$Proxy CreateInfo c1: class java.lang.Object
CGLIB$toString$2$Proxy CreateInfo c2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$hashCode$3$Proxy CreateInfo : class net.sf.cglib.proxy.MethodProxy$CreateInfo
CGLIB$hashCode$3$Proxy CreateInfo c1: class java.lang.Object
CGLIB$hashCode$3$Proxy CreateInfo c2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$clone$4$Proxy CreateInfo : class net.sf.cglib.proxy.MethodProxy$CreateInfo
CGLIB$clone$4$Proxy CreateInfo c1: class java.lang.Object
CGLIB$clone$4$Proxy CreateInfo c2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
*****************CreateInfo***********************
hi
proxy over
hi
*****************FastClassInfo***********************
Proxy Class: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
CGLIB$printHi$0$Proxy FastClassInfo : class net.sf.cglib.proxy.MethodProxy$FastClassInfo
CGLIB$printHi$0$Proxy FastClass f1: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$FastClassByCGLIB$$65f2d708
CGLIB$printHi$0$Proxy FastClass f2: class co.wangming.cglib.methodinterceptor.MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc$$FastClassByCGLIB$$19e0f1ba
CGLIB$printHi$0$Proxy FastClass i1: 0
CGLIB$printHi$0$Proxy FastClass i2: 14
---->
---->
---->
---->
****************FastClassInfo************************
由于生成的代理类的代码过于长, 而知乎没有折叠功能, 所以我将这个代码片段放到了码云上面 . A的代理类的名称是: MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc
cglib 动态代理 - 代码片段 - 码云 Gitee.comgitee.com
从printHi()方法入手, 看看它的代理是怎么实现的.
// 在MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc类内部, 有下面俩个和printHi方法相关的属性
上面简单分析了代理子类的实现, 但是这都不是重点, 真正的魔法在callback里面. demo里面callback是这么写的
enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {System.out.println("proxy start : " + proxy.getClass() + ": " + obj.getClass());Object res = proxy.invokeSuper(obj, args);System.out.println("proxy over");return res;
});
proxy参数的类型是MethodProxy类型, MethodProxy有俩个invoke方法:
- invoke(Object obj, Object[] args): obj参数不能是MethodInterceptor#intercept()方法的第一个参数obj对象, 否则会造成栈溢出
- invokeSuper(Object obj, Object[] args): obj参数必须是MethodInterceptor#intercept()方法的第一个参数obj对象
在使用MethodInterceptor的时候, 一定要注意上面这俩点, 下面我们就从invoke/invokeSuper方法入手, 分析一下.
由于这一块的源码过多, 我就不一一都贴出来了, 我画了俩张图帮大家理顺一下.
MethodProxy类里面有一个CreateInfo对象. CreateInfo内部有俩个Class对象, 分别是
- c1: 目标类的Class对象
- c2: 目标类的强化类的Class对象, 也就是CGLib生成的目标类的代理子类
CGLib会利用CreateInfo对象去构建出FastClassInfo这个对象. 构建过程就是通过CreateInfo的c1/c2去分别构建出FastClassInfo里面的FastClass类型的f1/f2.
也就是说, 真正的是构建了俩个FastClass对象出来. FastClass对象是通过FastClass内部类Generator进行构建的. 而内部类Generator是将构建过程交给了它的父类AbstractClassGenerator#generate()方法的.
AbstractClassGenerator#generate()又是通过其内部类GeneratorStrategy的对象执行了构建. 最终实现构建的是FastClass#Generator()的generateClass()方法, 该方法实例化了一个FastClassEmitter对象, FastClassEmitter对象内部就是通过ASM去构建Class对象的.
invoke/invokeSuper方法实现如下
public
init()方法如下
private
针对init()方法的过程可以参考一下下面的时序图
可以看出来, 整个CGLib的核心就在于这个FastClass
abstract
FastClass是一个抽象类, CGLib在运行时通过FastClass内的Generator这个内部类将其子类动态生成出来, 然后再利用ClassLoader将生成的子类加载进JVM里面去.
其实, CGLib会为我们生成很多个代理类, 不单单是目标类的子类, 例如上文提到的FastClass f1, FastClass f2的子类是不同的.
- MethodInterceptorTest$A$$FastClassByCGLIB$$65f2d708 : FastClassInfo#f1, MethodProxy的invoke()方法进行调用
- MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc$$FastClassByCGLIB$$19e0f1ba : FastClassInfo#f2, MethodProxy的invokeSuper()方法进行调用
public
在刚开始的demo中, 如果进行如下调用, 会发生递归.
eznhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {System.out.println("proxy start : " + proxy.getClass() + ": " + obj.getClass());Util.printCreateInfo(list.get(0));Object res2 = proxy.invoke(obj, args1); // 注意,这里将invokeSuper()换成了invoke()System.out.println("proxy over");return res2;});
这是因为(FastClassInfo#i1 的值为0, 因此var1为0, 刚开始的运行日志有输出 )
public
此时的var10000就是obj, 那么流畅就成了又会去调用MethodInterceptorTest$A$$EnhancerByCGLIB$$b5ca7abc的printHi()
public
因此当调用MethodProxy的invoke()方法时, 必须不能是MethodInterceptor#intercept的第一个obj参数.
而invokeSuper就不会有这个问题, FastClassInfo#i2的值为 14,
public
因此执行的是var10000.CGLIB$printHi$0();这个方法
final void CGLIB$printHi$0() {super.printHi();}
这是直接调用A的printHi()方法进行调用.
好了, 到这里分析就告一段落, 下次会分析下, cglib是如何利用ASM生成代理类的.
jdk动态代理实例和cglib动态代理实例_CGLib 动态代理 原理解析相关推荐
- 使用 cglib_java动态代理(JDK和CGLIB原理解析与使用)
CGLIB的动态代理 原理 代理为控制要访问的目标对象提供了一种途径.当访问对象时,它引入了一个间接的层.JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理.JDK的动态代理用起 ...
- 动态代理proxy与CGLib的区别
转载自 动态代理proxy与CGLib的区别 昨天被人问及动态代理与CGlib的区别,赶紧回顾一下: 什么是代理? 静态代理与动态代理 静态代理实例 JDK动态代理实例 CGLib 简介 CGLib ...
- 设计模式之代理模式、动态代理模式、Cglib代理模式
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用到编程中的 ...
- Java 动态代理 原理解析
概要 AOP的拦截功能是由java中的动态代理来实现的.说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常 ...
- Android插件化原理解析——Hook机制之动态代理
使用代理机制进行API Hook进而达到方法增强是框架的常用手段,比如J2EE框架Spring通过动态代理优雅地实现了AOP编程,极大地提升了Web开发效率:同样,插件框架也广泛使用了代理机制来增强系 ...
- java动态代理_Java 动态代理 原理解析
示例 需要代理的接口 public interface IHello {public void sayHello(); } 需要代理的类 public class HelloImpl implemen ...
- 动态代理最全详解系列[2]-Proxy生成代理类对象源码分析
之前我们通过JDK中的Proxy实现了动态代理,Proxy用起来是比较简便的,但理解起来不是那么清晰,是因为我们并没有看见代理类是怎么生成的,代理类怎么调用的被代理类方法,所以下面我们进入源码看一 ...
- 动态代理——拦截器——责任链——AOP面向切面编程底层原理详解(迪丽热巴版)
目录 动态代理模式详解 前言 什么是代理模式 如何进行代理 静态代理 动态代理 JDK动态代理 CGLIB动态代理 拦截器 责任链模式 博客文章版权申明 动态代理模式详解 前言 代理模式是设计模式中非 ...
- 动态代理源码分析,实现自己的动态代理
什么是代理 增强一个对象的功能 买火车票,app就是一个代理,他代理了火车站,小区当中的代售窗口 java当中如何实现代理 java实现的代理的两种办法 代理的名词 代理对象 增强后的对象 目标对象 ...
最新文章
- mysql-事务隔离级别
- 查理和政策配对工厂——设计一个问卷运算系统的B端到C端
- Hystrix面试 - 深入 Hystrix 执行时内部原理
- java操作Excel之POI(4)利用POI实现数据的批量导出
- f77编程和c语言的区别,在fortran中l用F77编译器编译程序时出现问题?
- 百度地图和openlayers融合封装(想法)
- 【算法练习】82.重复的DNA序列——哈希表
- Modis数据下载与处理(mrt、wget)
- 有谁知道千千静听中的波形特效是怎么做的?
- python输出课程表
- 用 Wwise 和 Unity 制作 DLC 使用 Wwise 文件包(File Package)
- Linux (CentOS) 系统下载地址
- 【Security】可信网络连接
- ZigBee 设置信道、PANID、发射功率
- ninja编译方法介绍
- ESP8266-01s——无线模块使用
- 使用第三方FTP软件进行文件传输的教程
- 中国广告灯箱市场现状调查与投资可行性分析报告2022-2028年
- oracle卸载crs,卸载ORACLE CRS
- R语言如何绘制簇状、堆积、填充柱形图(16)
热门文章
- log4j用于读取.xml文件的出现了错误,类加载器.getResource(user.xml).getPath()返回路径空格变成了%20...
- Objective-C中的KVC与KVO(上)
- 权限执行[Android开发常见问题-4] RunTime.exec()如何以root权限执行多条指令?
- JavaScript 中一句话的思索:this是函数在执行时所处的作用域
- 汇编语言之寄存器使用(bx,si,di,bp)
- 判断CSS与JS是否加载完毕的方法
- Sql中的递归问题-思考与建议
- 解决Debian 9 iwlwifi固件缺失导致无法连接无线网络的问题
- Redis安装异常解决办法
- idea中properties配置文件没有代码提示及代码高亮问题解决方案