在上一篇专栏中,分析了JDK动态代理的实现,而这一篇就是分析cglib动态代理的实现,建议先看上一篇专栏再看这一篇,由于二者之间都是大同小异的,可是JDK动态代理会更加好理解一点,换言之,也就是cglib比较难,不过理解了JDK动态代理再来看cglib的动态代理就会如鱼得水。java
cglib是经过生成一个被代理类的子类来实现动态代理的。也就是生成的动态代理类会继承被代理类。后面反编译动态代理类时就会清楚了。数组
methodProxy.invoke()
为何会栈溢出?同上一篇同样,咱们经过一个例子进行讲解,为了便于理解,例子也继续使用上一篇中的例子。缓存
建立一个须要被代理的类,由于cglib能够基于类进行代理(也能够基于接口代理),因此咱们不须要建立一个接口,直接建立一个类便可。mybatis
public class Hello {
public void sayHello(){
System.out.println("say hello");
}
}
复制代码
建立一个代理类,这个代理类须要实现一个MethodInterceptor
接口,与JDK动态代理的InvocationHandler
接口相似。函数
public class HelloInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before say hello");
// 1. 这里不能使用methodProxy.invoke(),会栈溢出,后面会有解释
// 2. 使用method.invoke()的时候不能使用参数中的o做为执行对象,不然也会发生
// 相似的栈溢出错误,必须自行另外建立一个新的对象,后面也会有解释
methodProxy.invokeSuper(o, objects);
System.out.println("after say hello");
return null;
}
}
复制代码
public class Test {
public static void main(String[] args) {
// 不使用缓存,使用缓存的话,复杂度会比较高,咱们只看如何生成代理类
System.setProperty("cglib.useCache", "false");
// 建立一个加强器
Enhancer enhancer = new Enhancer();
// 设置须要代理的类,等同于JDK中newProxyInstance的第二个参数
enhancer.setSuperclass(Hello.class);
// 设置代理类,等同于JDK中newProxyInstance的第三个参数
enhancer.setCallback(new HelloInterceptor());
// 建立动态代理类
Hello jack = (Hello) enhancer.create();
// 调用方法
jack.sayHello();
}
}
复制代码
分析源码的时候首先不考虑缓存的问题,由于考虑缓存的话,复杂度基本上都在缓存那里,有点脱离主题了,后面我会再分析带有缓存的源码。源码分析
该方法会建立一个代理class,而且返回一个该class的实例对象,也就是会返回一个动态代理类的实例对象,会使用被代理类(Hello.class)的无参构造post
public Object create() {
// 用于判断是否须要建立对象,false表示须要建立对象
classOnly = false;
// 由于使用的是无参构造,因此该属性为null
argumentTypes = null;
// 建立动态代理class的方法
return createHelper();
}
复制代码
若是被代理类是一个有参构造的类,那么可使用重载的create(Class[] argumentTypes, Object[] arguments)
,与上一个方法相似,只是多了参数类型测试
// 接收两个参数
// 1. 参数类型数组
// 2. 具体的参数数组
public Object create(Class[] argumentTypes, Object[] arguments) {
classOnly = false;
if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
throw new IllegalArgumentException("Arguments must be non-null and of equal length");
}
this.argumentTypes = argumentTypes;
this.arguments = arguments;
return createHelper();
}
复制代码
建立一个要生成的动态代理类的惟一键,用这个键来表示须要生成的动态代理类的惟一标识,而后将建立的工做委托给父类进行。this
private Object createHelper() {
// 检查设置的CallBack的类型是否符合要求
preValidate();
// 建立惟一标识
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
// 委托父类执行建立工做
Object result = super.create(key);
return result;
}
复制代码
调用了抽象的类生成器AbstractClassGenerator中的该方法。(若是)该方法将会尝试从缓存中spa
protected Object create(Object key) {
try {
// 获取ClassLoader,通常是AppClassLoader
ClassLoader loader = getClassLoader();
// classloader做为键,缓存的是经过该classloader加载的动态代理类
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
// 主要看这一句,这是建立而且获取动态代理类的地方,由于咱们不使用缓存
// 因此将会使用ASM直接建立一个动态代理类,而且使用ClassLoader 进行加载
// 因此这里返回的是一个Class对象。
Object obj = data.get(this, getUseCache());
// 若是返回的是Class对象,则建立一个该Class类的实例
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
// (在开启缓存的状况下才会执行到这里)若是返回的是一个
// EnhancerFactoryData对象,那么说明已经存在一个相应的动态代理Class对象
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
复制代码
从缓存中获取,由于咱们没有开启缓存,因此将会直接建立一个动态代理类
public Object get(AbstractClassGenerator gen, boolean useCache) {
// 这里useCache为false,因此直接经过抽象类生成器建立
if (!useCache) {
// 执行这一句。
// 传递了一个参数:ClassLoaderData.this,
// 这个参数是表示执行这段代码的ClassLoaderData对象,也就是标题的data对象
// 实际上直接写this也是同样,由于这个方法是属于ClassLoaderData这个内部类
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
复制代码
使用抽象的类生成器生成一个动态代理类,并使用类加载器加载
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
// 获取类加载,用于加载生成的动态代理类
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null while trying to define class " +
getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
"Please file an issue at cglib's issue tracker.");
}
synchronized (classLoader) {
// 生成动态代理类的类名,有兴趣能够研究一下,不难
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
if (attemptLoad) {
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 使用ASM生成动态代理类的class文件
// 咱们对具体是如何使用ASM生成class文件的过程不作分析
// 由于这须要对JVM结构和class文件结构很是熟悉才能理解
// 也不建议你们直接使用ASM(除非对class文件结构很是熟悉)。
byte[] b = strategy.generate(this);
// 获取生成的动态代理类的类名,应该与上面的name是同样的
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
// 经过classloader加载类文件,返回一个Class对象
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
// 返回生成的Class对象
return gen;
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
} finally {
CURRENT.set(save);
}
}
复制代码
而后将一直返回到super.create()
方法,获得一个动态代理类的Class对象。
由于返回的是一个Class对象,因此将会执行firstInstance()
方法,该方法实际就是经过Class对象获取到构造函数,经过构造函数建立一个实例出来,而后将实例返回。由于较简单,就不贴代码了。
只须要在测试类的最前面加上一个系统属性便可
public static void main(String[] args) {
// 输出生成的动态代理类
// 第二参数:输出的路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "H:\\mybatis_demo");
// 取消使用缓存,默认为true
System.setProperty("cglib.useCache", "false");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Hello.class);
enhancer.setCallback(new HelloInterceptor());
Hello jack = (Hello) enhancer.create();
jack.sayHello();
}
复制代码
public class Hello$$EnhancerByCGLIB$$35d006ca extends Hello implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$sayHello$0$Method;
private static final MethodProxy CGLIB$sayHello$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.lhd.cglib.Hello$$EnhancerByCGLIB$$35d006ca");
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$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "()V"}, (var1 = Class.forName("com.lhd.cglib.Hello")).getDeclaredMethods())[0];
CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "()V", "sayHello", "CGLIB$sayHello$0");
}
final void CGLIB$sayHello$0() {
super.sayHello();
}
public final void sayHello() {
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$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
} else {
super.sayHello();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1535311470:
if (var10000.equals("sayHello()V")) {
return CGLIB$sayHello$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public Hello$$EnhancerByCGLIB$$35d006ca() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
Hello$$EnhancerByCGLIB$$35d006ca var1 = (Hello$$EnhancerByCGLIB$$35d006ca)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);
Hello$$EnhancerByCGLIB$$35d006ca var10000 = new Hello$$EnhancerByCGLIB$$35d006ca();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Hello$$EnhancerByCGLIB$$35d006ca var10000 = new Hello$$EnhancerByCGLIB$$35d006ca();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Hello$$EnhancerByCGLIB$$35d006ca var10000 = new Hello$$EnhancerByCGLIB$$35d006ca;
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();
}
}
复制代码
经过输出的代理类咱们能够看到咱们输出的动态代理类其实是继承于被代理类的,而且重写了被代理类中的方法,由于是使用了继承,final类是没法被代理的,非final类的final方法也是没法被重写的。
动态生成的代理类其实是被代理类的一个子类。cglib不但重写了父类的方法,同时也重写了Object类中的toString()
,hashCode()
,equals()
,clone()
,没有重写wait()
,notify()
等方法是由于他们是final方法,没法重写。
当咱们拿到生成的代理类对象的时候,执行sayHello()
方法时,实际执行的是下面的代码
public final void sayHello() {
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$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
} else {
super.sayHello();
}
}
复制代码
当MethodInterceptor
类型的变量(例子中就是HelloInterceptor类)不为空时,将会执行该类中的intercept()
方法
咱们分析一下这个方法的参数:
CGLIB$STATICHOOK1()
方法中赋值,而该方法在最下面的静态代码块中被调用。被赋值为Hello类里面的sayHello
方法当咱们调用methodProxy.invoke(o, objects)
方法时,就会发生栈溢出。咱们看一下这个方法的内部是如何实现的
该方法接收两个参数:
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
// 会建立一个Hello类的FastClass类,该类用于较快调用指定的方法
// 主要是经过index下标来肯定须要执行的方法。有兴趣能够自行反编译查看
init();
FastClassInfo fci = fastClassInfo;
// 1
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalArgumentException e) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " + sig1);
throw e;
}
}
复制代码
1中的那行代码,就是真正执行方法的语句,咱们能够debug看内部的属性是什么
f1
是一个
Hello$$FastClassByCGLIB$$7572df32
类的对象,咱们能够在生成的动态代理类下面找到这个类,咱们打开这个类,并找到它的
invoke
方法
咱们执行这个方法传递的参数,能够看到i1
是0,黄色框部分。
咱们传递三个参数分别是:
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
Hello var10000 = (Hello)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.sayHello();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
复制代码
咱们经过这个源码能够看出实际上执行的是var10000.sayHello()
,而var10000
是咱们传递进来的动态代理对象,也就等于又执行了一次jack.sayHello();
,而jack.sayHello()
又会执行var10000.sayHello()
,因此一直互相调用,直到发生栈溢出。
咱们分析完上一个会发生栈溢出的方法调用后,咱们来分析一下不会发生栈溢出的方法调用的原理。
当咱们调用的时methodProxy.invokeSuper(o, objects);
时,就不会发生栈溢出的问题,咱们看一下这个方法的源码
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// 只有这一句不同
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
复制代码
f2
是
Hello$$EnhancerByCGLIB$$35d006ca$$FastClassByCGLIB$$518e6b66_3
,它是为生成的动态代理类生成的FastClass类。
咱们执行invoke方法传递的参数分别是:
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
35d006ca var10000 = (35d006ca)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
return var10000.toString();
case 2:
return new Integer(var10000.hashCode());
case 3:
return var10000.clone();
case 4:
return var10000.newInstance((Callback[])var3[0]);
case 5:
return var10000.newInstance((Callback)var3[0]);
case 6:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 7:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 8:
var10000.sayHello();
return null;
case 9:
35d006ca.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 10:
35d006ca.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 11:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 12:
return var10000.getCallbacks();
case 13:
return var10000.getCallback(((Number)var3[0]).intValue());
case 14:
return var10000.CGLIB$toString$2();
case 15:
return new Integer(var10000.CGLIB$hashCode$3());
case 16:
return var10000.CGLIB$clone$4();
case 17:
var10000.CGLIB$sayHello$0();
return null;
case 18:
return new Boolean(var10000.CGLIB$equals$1(var3[0]));
case 19:
return 35d006ca.CGLIB$findMethodProxy((Signature)var3[0]);
case 20:
35d006ca.CGLIB$STATICHOOK1();
return null;
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
复制代码
咱们能够看到17是var10000.CGLIB$sayHello$0();
,var10000
就是咱们传递进来的动态代理类对象,也就是执行了动态代理类对象的CGLIB$sayHello$0()
方法,咱们能够看一下这个方法的源码
final void CGLIB$sayHello$0() {
super.sayHello();
}
复制代码
实际上就是直接调用父类的sayHello方法,也就是最原始的那个方法。因此这里并不会出现互相调用的局面。
还剩下一个method.invoke(o, objects)
方法没有讲解。你们能够本身去debug一下看看会不会报错,原理跟methodProxy.invoke()
相似。
cglib动态代理和JDK动态代理本质的区别就是:
cglib动态代理的过程当中会生成三个Class文件(实际是五个,另外两个不须要理解),分别是:
cglib调用原始方法是经过FastClass的下标进行调用的。而JDK动态代理是经过反射进行调用的。
至此,cglib动态代理就讲完了,固然,ASM操做字节码生成动态代理文件部分由于不熟悉因此没有去讲解。可是不影响理解cglib动态代理的原理。写了两天,一共花了12个小时,加上debug,找资料,阅读源码,终于完成了。但愿你们看到错误的地方多多包涵,我会虚心请教。
这几天会总结出cglib动态代理和JDK动态代理的区别!