te static final void CGLIB$BIND_CALLBACKS(Object var0) {
Target$$EnhancerByCGLIB$$e7b1b1b0 var1 = (Target$$EnhancerByCGLIB$$e7b1b1b0)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];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
Target$$EnhancerByCGLIB$$e7b1b1b0 var10000 = new Target$$EnhancerByCGLIB$$e7b1b1b0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Target$$EnhancerByCGLIB$$e7b1b1b0 var10000 = new Target$$EnhancerByCGLIB$$e7b1b1b0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Target$$EnhancerByCGLIB$$e7b1b1b0 var10000 = new Target$$EnhancerByCGLIB$$e7b1b1b0;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
从代理对象反编译源码可以知道,代理对象继承于Target,拦截器调用intercept()方法,intercept()方法由自定义CGLibProxy实现,所以,最后调用CGLibProxy中的intercept()方法,从而完成了由代理对象访问到目标对象的动态代理实现。
1.2.3、jdk代理和cglib代理的总结
JDK动态代理:
. 需要目标类实现接口
. 生成的代理类是与目标类平级,实现了共同的接口
. 使用反射的方式进行最终方法的调用,性能较低
CGLIB动态代理:
. 不要求目标类实现接口
. 生成的代理类是目标类的子类
. final方法不会出现在代理类中
. 使用空间换时间的思想对最终的方法调用进行了优化,提升了运行时性能。
看到这里,大佬们此时是不是心里会产生个疑问:你的标题不是asm与cglib吗,前面说了这么多cglib代理和jdk代理,和asm有关系吗?哈哈,其实虽然我们没有再前面的内容中介绍asm的相关知识,但是其实字里行间都透漏着asm,整体总结一句就是CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
二、深入ASM
2.1、简介
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
与 BCEL 和 SERL 不同,ASM 提供了更为现代的编程模型。对于 ASM 来说,Java class 被描述为一棵树;使用 “Visitor” 模式遍历整个二进制结构;事件驱动的处理方式使得用户只需要关注于对其编程有意义的部分,而不必了解 Java 类文件格式的所有细节:ASM 框架提供了默认的"response taker"处理这一切。(官方文档:https://asm.ow2.io/asm4-guide.pdf *, *中文文档: https://cf.jd.com/pages/viewpage.action?pageId=1139356247 )
流程图
2.2、核心api介绍
ASM框架中的核心类有以下几个:
① ClassReader:该类用来解析编译过的class字节码文件。
② ClassWriter:该类用来重新构建编译后的类,比如说修改类名、属性以及方法,甚至可以生成新的类的字节码文件。
③ ClassAdapter:该类也实现了ClassVisitor接口,它将对它的方法调用委托给另一个ClassVisitor对象。
下面会列举每个核心类的几个核心api供大家参考,后面如果想了解更多的内容,可以直接查看asm的官方文档