1.说明
代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
2.类型:
CGLib动态代理和JDK动态代理
3.使用介绍
(1)CGLib动态代理的使用
使用示例:
1、针对代理类的示例
2 、针对代理接口的示例
(2)JDK动态代理的使用
4.底层分析(通过JVM添加参数-Dcglib.debugLocation=D:\IdeaProjects\cglib\cglib\target\classes【这个便是代理对象的存储路径】)
代理类的class类(依据文件TestObject$$EnhancerByCGLIB$$783a36a0.class)
(1)代码展示
(2)调用流程说明
当代理对象被调用的时候【假设为test()方法】
CGLIB$CALLBACK_0该属性一开始是没有值的(因为初始化过程没有赋值的步骤),而获取值得步骤在于 CGLIB$BIND_CALLBACKS(this);这一步。
这里面var1明显是指类本身,故CGLIB$BOUND会发现是布尔值类型,默认是false。而CGLIB$THREAD_CALLBACKS在静态代码块中被赋予了ThreadLocal,所以是打算从当前线程的ThreadLocal中获取。而CGLIB$STATIC_CALLBACKS类属性值中存放拦截方法数组的地方。然后返回数组的第一个元素过去。(1.这里有个问题ThreadLocal是什么时候被赋值的?)
(3)问题汇总
1.这里有个问题ThreadLocal是什么时候被赋值的?
是在 CGLIB$SET_THREAD_CALLBACKS 这个方法中被赋值的,CGLIB$SET_THREAD_CALLBACKS这个方法又是在newInstance方法【生成代理对象的方法】中被执行。
2 .test()⽅法内会去调⽤所设置的Callbacks中的intercept(),相当于执⾏增强逻辑,如果没有Callbacks,则会执⾏super.test(),那么我们⾃然能想到,如果不设置Callbacks,那是不是就能正常执⾏呢?(是不能正常执行的)
*
–
+ 情况1,enhancer.setCallback(null);
异常出现在:createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.IllegalStateException: Callback is null
*
–
+ 情况2,不设置enhancer.setCallback
createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.NullPointerException
(4)分析说明
5.JDK动态代理源码分析(还未写全,待续)
(1)Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
6.CGLib源码分析
(1)Enhancer.create()
(2)Enhancer.createHelper()
(3)AbstractClassGenerator.create(Object key)
(4)Enhancer.firstInstance((Class) obj) 与 Enhancer.createUsingReflection(type)
(5)ClassLoaderData.get(this, getUseCache())
7.MethodProxy源码分析
代码展示
代码说明
在使用过程,我们常常遇到methodProxy上的方法使用问题,然而根本不知道为什么会这样。(虽然也不怎么会这样用)
进行分析
(1)MethodProxy是什么时候创建出来的?
从上面的字节码文件可以看到是在静态方法CGLIB$STATICHOOK1()中生成的。
源代码为(MethodProxy类#create方法)
(2)MethodProxy的invoke 方法与invokeSuper方法的区别?
先上代码:
1.说白了,这个两个方法本身是根据不同的索引文件去找对应的方法,然后用传入对象,调用返回的方法。
2.这里面涉及了另外的两个字节码文件(便是上面存储路径下的):
TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class(这里面是代理类的方法索引)
TestObject$$FastClassByCGLIB$$a3bbba2f.class (这里面是目标类的方法索引)
(3)FastClassInfo的生成过程
TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class代码展示(已经进行了部分删减,可以尝试自己去调试生产厂)
8.拓展内容
ASM技术
引入包类
代码示例
Javassist技术
引入包类
代码示例
Original: https://www.cnblogs.com/chafry/p/16709585.html
Author: 忧愁的chafry
Title: java的动态代理底层解析
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/620418/
转载文章受原作者版权保护。转载请注明原作者出处!