CGLIB源码易懂解析
Posted Fire king
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CGLIB源码易懂解析相关的知识,希望对你有一定的参考价值。
CGLIB源码易懂解析
1.测试代码
public class InfoDemo
public void welcome (String person)
System.out.println("welcome :" + person);
public class CglibInfoProxy implements MethodInterceptor
private Object target;
public Object newInstance(Object source)
target = source;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
System.out.println("before method!!!");
//生成的代理类字节码中调用
Object value = methodProxy.invokeSuper(o, objects);
//Object value = methodProxy.invoke(o, objects);
return value;
public static void main(String[] args)
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\\\development\\\\classes");
InfoDemo instance = (InfoDemo) new CglibInfoProxy().newInstance(new InfoDemo());
instance.welcome("zhangsan");
2.运行后生成的三个字节码文件
代理类:InfoDemo$$EnhancerByCGLIB$$45152a9a.class
代理类的FastClass:
InfoDemo$$EnhancerByCGLIB$$45152a9a$$FastClassByCGLIB$$778b2fd5.class
被代理类的FastClass:InfoDemo$$FastClassByCGLIB$$6332e5ad.class
3.源码追溯
①主方法生成代理对象的demo块运行后出现了三个字节码文件,如2所示
InfoDemo instance = (InfoDemo) new CglibInfoProxy().newInstance(new InfoDemo());
newInstance方法的细节:
public Object newInstance(Object source)
target = source;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
②InfoDemo$$EnhancerByCGLIB$$45152a9a.class有一块静态代码块会初始化一些数据,如下:
static
CGLIB$STATICHOOK1();
static void CGLIB$STATICHOOK1()
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("test.InfoDemo$$EnhancerByCGLIB$$45152a9a");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;", (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$welcome$0$Method = ReflectUtils.findMethods(new String[]"welcome", "(Ljava/lang/String;)V", (var1 = Class.forName("test.InfoDemo")).getDeclaredMethods())[0];
CGLIB$welcome$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "welcome", "CGLIB$welcome$0");
这里只要记住一点var1赋值过两次,都是在ReflectUtils中findMethods方法赋值的:
1.Object类
2.被代理类InfoDemo
var0是代理类
MethodProxy.create参数格式:
var1,var0,方法描述符,var1的方法,var0的方法 |
③instance.welcome("zhangsan");
JVM会调用代理类字节码文件InfoDemo$$EnhancerByCGLIB$$45152a9a.class的welcome方法,如下:
public final void welcome(String var1)
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null)
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
if (var10000 != null)
var10000.intercept(this, CGLIB$welcome$0$Method, new Object[]var1, CGLIB$welcome$0$Proxy);
else
super.welcome(var1);
疑云:
1.CGLIB$CALLBACK_0从哪来
2.CGLIB$BIND_CALLBACKS做了什么
3.intercept方法又是什么
解答:
1.CGLIB$CALLBACK_0有可能一开始就应该为空,又或者在到这步之前赋过值,但是细看如下代码,既让对var10000进行判空,那么有极大甚至说90%可能到这步理应为空,所以说我们暂时先走 CGLIB$BIND_CALLBACKS(this);
的逻辑。
if (var10000 == null)
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
④CGLIB$BIND_CALLBACKS(this);
private static final void CGLIB$BIND_CALLBACKS(Object var0)
InfoDemo$$EnhancerByCGLIB$$45152a9a var1 = (InfoDemo$$EnhancerByCGLIB$$45152a9a)var0;
if (!var1.CGLIB$BOUND)
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null)
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null)
return;
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
疑云:
1.CGLIB$BOUND的true or false
2.有CGLIB$THREAD_CALLBACKS.get();
应该在之前哪里调用代理类的set方法set过
3.CGLIB$STATIC_CALLBACKS又是哪里来的
解答:
1.对于整块代码,核心都是当GLIB$BOUND=false才执行,姑且认为是false
2.CGLIB$THREAD_CALLBACKS.get();
在生成代理类的enhancer.create()
中set过,因此,转到⑤看下具体逻辑验证。
3.CGLIB$STATIC_CALLBACKSza在Enhancer
类中有生成过方法签名,也许在enhancer.create()
的时候执行过。
⑤enhancer.create()
一路追到protected Object create(Object key)
方法,
return obj instanceof Class ? this.firstInstance((Class)obj) : this.nextInstance(obj);
先看firstInstance
,再追到
private static void setThreadCallbacks(Class type, Callback[] callbacks)
setCallbacksHelper(type, callbacks, "CGLIB$SET_THREAD_CALLBACKS");
深度调用:可以看出执行了名为“CGLIB$SET_THREAD_CALLBACKS”的方法
private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName)
try
Method setter = getCallbacksSetter(type, methodName);
setter.invoke((Object)null, callbacks);
catch (NoSuchMethodException var4)
throw new IllegalArgumentException(type + " is not an enhanced class");
catch (IllegalAccessException var5)
throw new CodeGenerationException(var5);
catch (InvocationTargetException var6)
throw new CodeGenerationException(var6);
我们去搜一下代理类的“CGLIB$SET_THREAD_CALLBACKS”方法,果然
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0)
CGLIB$THREAD_CALLBACKS.set(var0);
最后我们再回到④
由于var10000不再是空了,所以直接走下面的逻辑
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
这段代码的释义:
var10000引用赋值给Callback[],Callback[]的第一个槽位就是var10000所指对象,再强转成MethodInterceptor引用赋值给CGLIB$CALLBACK_0。因此③中 var10000 = this.CGLIB\\$CALLBACK_0;
,var10000就有值了,而且最后的值是代理类(var10000多次变幻)。
⑥接③var10000.intercept(this, CGLIB$welcome$0$Method, new Object[]var1, CGLIB$welcome$0$Proxy);
我们说过var10000最终是代理类,所以会执行代理类的intercept方法,如下:
先输出,再调methodProxy.invokeSuper(o, objects);
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
System.out.println("before method!!!");
Object value = methodProxy.invokeSuper(o, objects);
return value;
⑦methodProxy.invokeSuper(o, objects);
由 MethodProxy.FastClassInfo fci = this.fastClassInfo;
可以看出是FastClass,再由fci.f2.invoke(fci.i2, obj, args);
可知是代理类的FastClass调用invoke方法(fci.f2是代理类的FastClass,那么fci.f1是被代理类的FastClass)
public Object invokeSuper(Object obj, Object[] args) throws Throwable
try
this.init();
MethodProxy.FastClassInfo fci = this.fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
catch (InvocationTargetException var4)
throw var4.getTargetException();
疑惑:
1.fci.i2的值从哪里来
解答:
this.init();
private void init()
if (this.fastClassInfo == null)
synchronized(this.initLock)
if (this.fastClassInfo == null)
MethodProxy.CreateInfo ci = this.createInfo;
MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(this.sig1);
fci.i2 = fci.f2.getIndex(this.sig2);
this.fastClassInfo = fci;
this.createInfo = null;
我们不难发现fci.f1和fci.f2分别是被代理类FastClass和代理类的FastClass,因此这两个方法需分别到对应的class文件去看实现。
fci.i1 = fci.f1.getIndex(this.sig1);
fci.i2 = fci.f2.getIndex(this.sig2);
我们看代理类的FastClass的getIndex方法:
不难看出,是通过散列值去返回一些整型值赋值给fci.i2。我们重点关注与被代理类方法调用的返回值,例如8,因此,我们明确了fci.i2=8。
public int getIndex(Signature var1)
String var10000 = var1.toString();
switch(var10000.hashCode())
case -1882565338:
if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z"))
return 17;
break;
case -1870561232:
if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;"))
return 9;
break;
case -1745842178:
if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V"))
return 10;
break;
case -1641413109:
if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;"))
return 5;
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V"))
return 15;
break;
case -1411842725:
if (var10000.equals("CGLIB$hashCode$3()I"))
return 19;
break;
case -1034266769:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V"))
return 11;
break;
case -1025895669:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V"))
return 12;
break;
case -988317324:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;"))
return 6;
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;"))
return 3;
break;
case 233072605:
if (var10000.equals("welcome(Ljava/lang/String;)V"))
return 8;
break;
case 610042816:
if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;"))
return 4;
break;
case 1013143764:
if (var10000.equals("CGLIB$welcome$0(Ljava/lang/String;)V"))
return 16;
break;
case 1132856532:
if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;"))
return 14;
break;
case 1246779367:
if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V"))
return 7;
break;
case 1306468936:
if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;"))
return 18;
break;
case 1364367423:
if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;"))
return 13;
break;
case 1800494055:
if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;"))
return 20Java动态代理——JDK和CGlib(简单易懂)