CGLIB动态代理源码分析

CGLIB动态代理样例

由于CGLIB是JDK之外的东西,因此在使用CGLIB的时候需要引入CGLIB的包(我这里是gradle项目):

dependencies { implementation('cglib:cglib:3.3.0') }

要被代理的类:

1package com.example.demo.proxy.cglib; 2 3public class Hello { 4 public void sayHello(String name) { 5 System.out.println("Hello " + name); 6 } 7}

一个自定义的方法拦截器,该拦截器实现了net.sf.cglib.proxy.MethodInterceptor接口:

1package com.example.demo.proxy.cglib; 2 3import net.sf.cglib.proxy.MethodInterceptor; 4import net.sf.cglib.proxy.MethodProxy; 5 6import java.lang.reflect.Method; 7 8public class MyMethodInterceptor implements MethodInterceptor { 9 @Override 10 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 11 System.out.println(">>>> Before method invocation"); 12 Object object = proxy.invokeSuper(obj, args); 13 System.out.println(">>>> After method invocation"); 14 return object; 15 } 16}

主测试类CglibProxyDemo.java:

1package com.example.demo.proxy.cglib; 2 3import net.sf.cglib.core.DebuggingClassWriter; 4import net.sf.cglib.proxy.Enhancer; 5 6/** 7 * Cglib proxy demo. 8 * Main implementation steps: 9 * 1. Implement the net.sf.cglib.proxy.MethodInterceptor interface 10 * 2. Create Enhancer object(which is used to create proxy object), set target class and callback object. 11 * 3. Create proxy object by invoke enhancer.create() 12 * 4. Call method on proxy object 13 */ 14public class CglibProxyDemo { 15 public static void main(String[] args) { 16 //Generate proxy class under given path 17 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "out"); 18 19 //2. Create Enhancer object, which is used to create proxy object. 20 Enhancer enhancer = new Enhancer(); 21 enhancer.setSuperclass(Hello.class); //Set target class 22 enhancer.setCallback(new MyMethodInterceptor()); //Set callback object 23 24 //3. Create proxy by invoke enhancer.create(). 25 Hello helloProxy = (Hello) enhancer.create(); 26 27 //4. Call method on proxy object. 28 helloProxy.sayHello("Doris"); 29 } 30}

执行结果:

可以看到,原来的Hello.sayHello()方法已经被代理了,加入了调用的前置处理和后置处理。

源码分析

先看看主测试类CglibProxyDemo.java,里面创建了一个enhancer,并且给它设置了superClass和callback两个属性,然后用这个enhancer创建了一个代理对象helloProxy,最后调用了代理对象的sayHello()方法。

创建代理对象 Hello helloProxy = (Hello) enhancer.create();

1.获取Key

代理对象helloProxy通过以下语句创建:

Hello helloProxy = (Hello) enhancer.create();

在Enhancer中:

1/** 2 * Generate a new class if necessary and uses the specified 3 * callbacks (if any) to create a new object instance. 4 * Uses the no-arg constructor of the superclass. 5 * @return a new instance 6 */ 7public Object create() { 8 classOnly = false; 9 argumentTypes = null; 10 return createHelper(); 11}

在createHelper()中,创建了一个唯一的key,用于在缓存中存取代理类的Class实例,并且立即调用父类AbstractClassGenerator.create(Object key)方法创建代理类的实例:

1private Object createHelper() { 2 preValidate(); 3 //创建key,用于在缓存中存取代理类实例 4 Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, 5 ReflectUtils.getNames(interfaces), 6 filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter), 7 callbackTypes, 8 useFactory, 9 interceptDuringConstruction, 10 serialVersionUID); 11 this.currentKey = key; 12 //调用父类AbstractClassGenerator.create()创建代理类实例 13 Object result = super.create(key); 14 return result; 15}

在create()中,会调用内部类ClassLoaderDataget(AbstractClassGenerator gen, boolean useCache)方法获取代理类的Class实例:

1protected Object create(Object key) { 2 try { 3 ClassLoader loader = getClassLoader(); 4 Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> cache = CACHE; 5 AbstractClassGenerator.ClassLoaderData data = cache.get(loader); 6 if (data == null) { 7 synchronized (AbstractClassGenerator.class) { 8 cache = CACHE; 9 //加锁后再试一次,如果还没取到,就创建缓存 10 data = cache.get(loader); 11 if (data == null) { 12 Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> newCache = new WeakHashMap<ClassLoader, AbstractClassGenerator.ClassLoaderData>(cache); 13 data = new AbstractClassGenerator.ClassLoaderData(loader); 14 newCache.put(loader, data); 15 CACHE = newCache; 16 } 17 } 18 } 19 this.key = key; 20 //从ClassLoaderData中获取代理类的Class实例 21 Object obj = data.get(this, getUseCache()); 22 if (obj instanceof Class) { 23 //获取代理类的实例 24 return firstInstance((Class) obj); 25 } 26 return nextInstance(obj); 27 } catch (RuntimeException e) { 28 throw e; 29 } catch (Error e) { 30 throw e; 31 } catch (Exception e) { 32 throw new CodeGenerationException(e); 33 } 34}

2.通过Key从缓存中获取Class

在ClassLoaderData中,有个字段generatedClasses,这个对象存放着当前类加载器加载的代理类的Class类实例,下面的方法本质,就是从这个generatedClasses里面匹配

1//只要代理类的classLoader存在,这些代理类就是可以重用的 2//通过generatedClasses缓存是获取代理类的唯一方法 3private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses; 4 5// ... 6 7public Object get(AbstractClassGenerator gen, boolean useCache) { 8 //默认是使用缓存的,可以通过以下属性设置不使用缓存 9 //System.setProperty("cglib.useCache", "false") 10 if (!useCache) { 11 return gen.generate(AbstractClassGenerator.ClassLoaderData.this); 12 } else { 13 //从generatedClasses中获取Class对象 14 Object cachedValue = generatedClasses.get(gen); 15 return gen.unwrapCachedValue(cachedValue); 16 } 17}

再来看看LoadingCache这个类,需要重点理解这三个字段:

1//K:AbstractClassGenerator 这里指Enhancer类 2//KK:Object 这里指前面生成key的类 3//V:Object 这里指代理类的Class类 4public class LoadingCache<K, KK, V> { 5 //通过key可以拿到代理类的Class实例 6 protected final ConcurrentMap<KK, Object> map; 7 //通过loader.apply(Enhancer实例)可以获得代理类的Class实例 8 protected final Function<K, V> loader; 9 //通过keyMapper.apply(Enhancer实例)可以获得key 10 protected final Function<K, KK> keyMapper; 11 12 //······· 13}

在get方法中,通过key生成的cachKey去缓存中查找,如果没找到,则创建Class实例,并放入缓存map中:

1public V get(K key) { 2 //通过key生成cacheKey 3 final KK cacheKey = keyMapper.apply(key); 4 //通过cacheKey查找缓存 5 Object v = map.get(cacheKey); 6 if (v != null && !(v instanceof FutureTask)) { 7 return (V) v; 8 } 9 //如果没找到,就创建Class实例,并放入缓存 10 return createEntry(key, cacheKey, v); 11}

3.生成代理类Class

1//LoadingCache.createEntry() 2//省略了无关代码 3protected V createEntry(final K key, KK cacheKey, Object v) { 4 //创建Class实例 5 V result = loader.apply(key); 6 //放入缓存中 7 map.put(cacheKey, result); 8 return result; 9}

loader是一个Function,是创建LoadingCache的时候通过构造器传入的,loader是在AbstractClassGenerator的内部类ClassLoaderData中创建的:

1//AbstractClassGenerator$ClassLoaderData的构造函数 2Function<AbstractClassGenerator, Object> load = 3 new Function<AbstractClassGenerator, Object>() { 4 public Object apply(AbstractClassGenerator gen) { 5 //生成一个class的字节码 6 Class klass = gen.generate(ClassLoaderData.this); 7 return gen.wrapCachedClass(klass); 8 } 9 }; 10generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);

4.创建代理对象

创建了代理类的Class对象后,通过AbstractClassGenerator.firstInstance(Class type)来创建代理类的实例,该方法是一个abstract方法,实现在Enhancer中:

1//Enhancer 2protected Object firstInstance(Class type) throws Exception { 3 if (classOnly) { 4 return type; 5 } else { 6 //会执行到这里 7 return createUsingReflection(type); 8 } 9} 10 11/** 12 * Instantiates a proxy instance and assigns callback values. 13 * Implementation detail: java.lang.reflect instances are not cached, so this method should not 14 * be used on a hot path. 15 * This method is used when {@link #setUseCache(boolean)} is set to {@code false}. 16 * 17 * @param type class to instantiate 18 * @return newly created instance 19 */ 20private Object createUsingReflection(Class type) { 21 setThreadCallbacks(type, callbacks); 22 try{ 23 if (argumentTypes != null) { 24 return ReflectUtils.newInstance(type, argumentTypes, arguments); 25 } else { 26 return ReflectUtils.newInstance(type); 27 } 28 } finally { 29 // clear thread callbacks to allow them to be gc'd 30 setThreadCallbacks(type, null); 31 } 32}

最后就是通过反射创建了代理类的实例。

调用代理对象的方法 helloProxy.sayHello("Doris");

1.代理类的源码分析

从测试结果可以看到,对于helloProxy.sayHello("Doris");的调用,最终调用到了MyInterceptor.intercept()方法上,为什么呢?先看下debug模式下的helloProxy的类型:

可以看到,helloProxy对象的类型是“Hello$$EnhancerByCGLIB$$190a8bdd”,这是一个CGLIB生成的用于代理Hello的代理类,并且其CGLIB$CALLBACK_0属性就是我们通过enhancer.setCallback()设置的MyMethodInterceptor。

为了便于分析,我们通过第一句保留了CGLIB生成的动态代理的文件在项目根目录的out文件夹下:

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "out");

在IDEA中打开打开这个生成的代理类:

1package com.example.demo.proxy.cglib; 2 3import java.lang.reflect.Method; 4import net.sf.cglib.core.ReflectUtils; 5import net.sf.cglib.core.Signature; 6import net.sf.cglib.proxy.Callback; 7import net.sf.cglib.proxy.Factory; 8import net.sf.cglib.proxy.MethodInterceptor; 9import net.sf.cglib.proxy.MethodProxy; 10 11//可以看到这个代理类是Hello的子类,并且实现了Factory接口,该接口主要用于实例化对象和设置回调函数。 12//生成的类名的规则:被代理ClassName + "$$" + ClassGeneratorName + "ByCGLIB" + "$$" + key的hashCode 13public class Hello$$EnhancerByCGLIB$$190a8bdd extends Hello implements Factory { 14 private boolean CGLIB$BOUND; 15 public static Object CGLIB$FACTORY_DATA; 16 private static final ThreadLocal CGLIB$THREAD_CALLBACKS; 17 private static final Callback[] CGLIB$STATIC_CALLBACKS; 18 private MethodInterceptor CGLIB$CALLBACK_0; 19 private static Object CGLIB$CALLBACK_FILTER; 20 21 //这里有很多属性,基本上一个Method对应一个MethodProxy 22 private static final Method CGLIB$sayHello$0$Method;//被代理的sayHello()方法 23 private static final MethodProxy CGLIB$sayHello$0$Proxy;//代理的sayHello()方法 24 private static final Object[] CGLIB$emptyArgs; 25 private static final Method CGLIB$equals$1$Method; 26 private static final MethodProxy CGLIB$equals$1$Proxy; 27 private static final Method CGLIB$toString$2$Method; 28 private static final MethodProxy CGLIB$toString$2$Proxy; 29 private static final Method CGLIB$hashCode$3$Method; 30 private static final MethodProxy CGLIB$hashCode$3$Proxy; 31 private static final Method CGLIB$clone$4$Method; 32 private static final MethodProxy CGLIB$clone$4$Proxy; 33 34 // 静态代码块,主要是通过【反射】获取了以下方法的字节码: 35 // Object.equals() 36 // Object.toString() 37 // Object.hashCode() 38 // Object.clone() 39 // Hello.sayHello() 40 // 并为这些方法创建对应的MethodProxy 41 static void CGLIB$STATICHOOK1() { 42 CGLIB$THREAD_CALLBACKS = new ThreadLocal(); 43 CGLIB$emptyArgs = new Object[0]; 44 //代理类Class对象 45 Class var0 = Class.forName("com.example.demo.proxy.cglib.Hello$$EnhancerByCGLIB$$190a8bdd"); 46 //被代理类Class对象 47 Class var1; 48 //被代理类var1在这一行被赋值为java.lang.Object 49 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()); 50 CGLIB$equals$1$Method = var10000[0]; 51 CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1"); 52 CGLIB$toString$2$Method = var10000[1]; 53 CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2"); 54 CGLIB$hashCode$3$Method = var10000[2]; 55 CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3"); 56 CGLIB$clone$4$Method = var10000[3]; 57 CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4"); 58 //被代理类var1在这一行被赋值为com.example.demo.proxy.cglib.Hello 59 CGLIB$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "(Ljava/lang/String;)V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.Hello")).getDeclaredMethods())[0]; 60 //这里创建了sayHello方法的代理 61 CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "sayHello", "CGLIB$sayHello$0"); 62 } 63 64 //这个方法就是调用目标类的sayHello()方法 65 final void CGLIB$sayHello$0(String var1) { 66 super.sayHello(var1); 67 } 68 69 //这个方法就是sayHello()方法在代理对象中的实现,即在我们样例中helloProxy.sayHello()调用的方法 70 public final void sayHello(String var1) { 71 MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; 72 if (var10000 == null) { 73 CGLIB$BIND_CALLBACKS(this); 74 var10000 = this.CGLIB$CALLBACK_0; 75 } 76 77 //var10000就是样例中enhancer.setCallback(new MyMethodInterceptor());设置的方法拦截器 78 if (var10000 != null) { 79 //如果方法拦截器存在,就调用它的interceptor方法。就会调用MyMethodInterceptor.intercept()方法 80 var10000.intercept(this, CGLIB$sayHello$0$Method, new Object[]{var1}, CGLIB$sayHello$0$Proxy); 81 } else { 82 //如果方法拦截器不存在,就只执行目标类的sayHello()方法 83 super.sayHello(var1); 84 } 85 } 86 87 //... 88 //省略了equals, toString, hashCode, clone等方法的实现,逻辑都是类似的: 89 //如果方法拦截器存在,就调用拦截器的intercept方法,否则直接调用父类的方法 90 //... 91 92 public static MethodProxy CGLIB$findMethodProxy(Signature var0) { 93 String var10000 = var0.toString(); 94 switch(var10000.hashCode()) { 95 case -508378822: 96 if (var10000.equals("clone()Ljava/lang/Object;")) { 97 return CGLIB$clone$4$Proxy; 98 } 99 break; 100 case 771401912: 101 if (var10000.equals("sayHello(Ljava/lang/String;)V")) { 102 return CGLIB$sayHello$0$Proxy; 103 } 104 break; 105 case 1826985398: 106 if (var10000.equals("equals(Ljava/lang/Object;)Z")) { 107 return CGLIB$equals$1$Proxy; 108 } 109 break; 110 case 1913648695: 111 if (var10000.equals("toString()Ljava/lang/String;")) { 112 return CGLIB$toString$2$Proxy; 113 } 114 break; 115 case 1984935277: 116 if (var10000.equals("hashCode()I")) { 117 return CGLIB$hashCode$3$Proxy; 118 } 119 } 120 121 return null; 122 } 123 124 //无参构造函数 125 public Hello$$EnhancerByCGLIB$$190a8bdd() { 126 CGLIB$BIND_CALLBACKS(this); 127 } 128 129 public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { 130 CGLIB$THREAD_CALLBACKS.set(var0); 131 } 132 133 public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) { 134 CGLIB$STATIC_CALLBACKS = var0; 135 } 136 137 private static final void CGLIB$BIND_CALLBACKS(Object var0) { 138 Hello$$EnhancerByCGLIB$$190a8bdd var1 = (Hello$$EnhancerByCGLIB$$190a8bdd)var0; 139 if (!var1.CGLIB$BOUND) { 140 var1.CGLIB$BOUND = true; 141 Object var10000 = CGLIB$THREAD_CALLBACKS.get(); 142 if (var10000 == null) { 143 var10000 = CGLIB$STATIC_CALLBACKS; 144 if (var10000 == null) { 145 return; 146 } 147 } 148 149 var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; 150 } 151 152 } 153 154 //... 155 //省略了实现的Factory接口的方法 156 //... 157 158 //调用静态代码块,完成Method和MethodProxy的初始化 159 static { 160 CGLIB$STATICHOOK1(); 161 } 162}

可以看到,当在代理对象上调用sayHello()方法时,会先检查这个代理对象是否有MethodInterceptor,如果有,则调用其intercept方法,没有则直接调用目标对象的sayHello()方法。这里就进入到了MyMethodInterceptor.intercept()方法,打印了这句话:

>>>> Before method invocation

2. MethodProxy.invokeSuper()

这里的MethodProxy是在代理类的静态块CGLIB$STATICHOOK1中通过创建的:

1//Hello$$EnhancerByCGLIB$$190a8bdd 2CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "sayHello", "CGLIB$sayHello$0"); 3 4//MethodProxy 5public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) { 6 MethodProxy proxy = new MethodProxy(); 7 proxy.sig1 = new Signature(name1, desc); 8 proxy.sig2 = new Signature(name2, desc); 9 //创建了createInfo属性 10 proxy.createInfo = new MethodProxy.CreateInfo(c1, c2); 11 return proxy; 12}

这里创建了proxy对象的createInfo属性,接下来会在invokeSuper()方法中调用init()方法的时候,用该属性来创建FastClass类

1public Object invokeSuper(Object obj, Object[] args) throws Throwable { 2 try { 3 //初始化,创建了两个FastClass类对象,并根据原来的方法签名得到方法索引 4 init(); 5 //这个对象持有两个FastClass类对象和方法的索引,见下方FastClassInfo类 6 MethodProxy.FastClassInfo fci = fastClassInfo; 7 //f2是代理对象的FastClass,这里是调用代理对象上索引为i2的方法 8 return fci.f2.invoke(fci.i2, obj, args); 9 } catch (InvocationTargetException e) { 10 throw e.getTargetException(); 11 } 12} 13 14private void init() { 15 if (fastClassInfo == null) { 16 synchronized (initLock) { 17 if (fastClassInfo == null) { 18 //用createInfo属性来创建FastClassInfo 19 MethodProxy.CreateInfo ci = createInfo; 20 MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo(); 21 22 //helper方法用ASM框架生成了两个FastClass类 23 fci.f1 = helper(ci, ci.c1);//目标类的FastClass 24 fci.f2 = helper(ci, ci.c2);//代理类的FastClass 25 26 //分别从FastClass中获取指定签名的方法 27 fci.i1 = fci.f1.getIndex(sig1);//在目标类的FastClass中获取方法索引 28 fci.i2 = fci.f2.getIndex(sig2);//在代理类的FastClass中获取方法索引 29 30 //将fci赋值给全局变量fastClassInfo 31 fastClassInfo = fci; 32 createInfo = null; 33 } 34 } 35 } 36} 37 38private static class FastClassInfo { 39 //目标类的FastClass类 40 FastClass f1; 41 //代理类的FastClass类 42 FastClass f2; 43 //目标类FastClass中的方法索引 44 int i1; 45 //代理类FastClass中的方法索引 46 int i2; 47}

这里主要是通过MethodProxy.init()方法为目标类和代理类分别创建了FastClass,然后初始化了一个FastClassInfo对象(该对象持有两个FastClass以及FastClass中对于该方法的索引),最后在代理对象上调用了invoke方法。

3.FastClass类的代码分析

来看看代理类的FastClass(就是CGLIB生成的文件名最长的类),它是net.sf.cglib.reflect.FastClass的子类,主要用于给指定的类(这里是代理类)建立方法索引,避免每次使用反射去调用方法。该类里面主要是通过方法签名(Signature)获取方法索引(index)的方法,以及通过方法索引(index)调用方法的方法。

1package com.example.demo.proxy.cglib; 2 3import com.example.demo.proxy.cglib.Hello..EnhancerByCGLIB..190a8bdd; 4import java.lang.reflect.InvocationTargetException; 5import net.sf.cglib.core.Signature; 6import net.sf.cglib.reflect.FastClass; 7 8public class Hello$$EnhancerByCGLIB$$190a8bdd$$FastClassByCGLIB$$cbc4a17e extends FastClass { 9 public Hello$$EnhancerByCGLIB$$190a8bdd$$FastClassByCGLIB$$cbc4a17e(Class var1) { 10 super(var1); 11 } 12 13 //通过方法签名获取方法的索引,该索引将用于快速调用方法(下面invoke方法中的case) 14 public int getIndex(Signature var1) { 15 String var10000 = var1.toString(); 16 switch(var10000.hashCode()) { 17 case 771401912: 18 if (var10000.equals("sayHello(Ljava/lang/String;)V")) { 19 return 14; 20 } 21 break; 22 //...省略其他的case 23 } 24 return -1; 25 } 26 27 //通过方法名和参数类型获取方法的索引。比如var1="sayHello", var2=[java.lang.String] 28 /** 29 * Return the index of the matching method. The index may be used 30 * later to invoke the method with less overhead. If more than one 31 * method matches (i.e. they differ by return type only), one is 32 * chosen arbitrarily. 33 * @see #invoke(int, Object, Object[]) 34 * @param name the method name 35 * @param parameterTypes the parameter array 36 * @return the index, or <code>-1</code> if none is found. 37 */ 38 public int getIndex(String var1, Class[] var2) { 39 switch(var1.hashCode()) { 40 case -2012993625: 41 if (var1.equals("sayHello")) { 42 switch(var2.length) { 43 case 1: 44 if (var2[0].getName().equals("java.lang.String")) { 45 return 14; 46 } 47 } 48 } 49 break; 50 //...省略其他的case 51 } 52 return -1; 53 } 54 55 //通过参数类型获取构造器的索引,该索引用于稍后创建实例(下面newInstance方法中的case) 56 /** 57 * Return the index of the matching constructor. The index may be used 58 * later to create a new instance with less overhead. 59 * @see #newInstance(int, Object[]) 60 * @param parameterTypes the parameter array 61 * @return the constructor index, or <code>-1</code> if none is found. 62 */ 63 public int getIndex(Class[] var1) { 64 switch(var1.length) { 65 //只有一个默认的无参构造器,因此只有一个case 0 66 case 0: 67 return 0; 68 default: 69 return -1; 70 } 71 } 72 73 //调用方法(注释来自FastClass类) 74 /** 75 * Invoke the method with the specified index. 76 * @see getIndex(name, Class[]) 77 * @param index the method index 78 * @param obj the object the underlying method is invoked from 79 * @param args the arguments used for the method call 80 * @throws java.lang.reflect.InvocationTargetException if the underlying method throws an exception 81 */ 82 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { 83 190a8bdd var10000 = (190a8bdd)var2; 84 int var10001 = var1; 85 86 try { 87 switch(var10001) { 88 //这里的case的情况都由getIndex(Signature var1)方法 89 //或getIndex(String var1, Class[] var2)方法返回 90 case 14: 91 var10000.sayHello((String)var3[0]); 92 return null; 93 //...省略其他的case 94 } 95 } catch (Throwable var4) { 96 throw new InvocationTargetException(var4); 97 } 98 99 throw new IllegalArgumentException("Cannot find matching method/constructor"); 100 } 101 102 //通过构造器实例化对象(注释来自FastClass类) 103 /** 104 * Create a new instance using the specified constructor index and arguments. 105 * @see getIndex(Class[]) 106 * @param index the constructor index 107 * @param args the arguments passed to the constructor 108 * @throws java.lang.reflect.InvocationTargetException if the constructor throws an exception 109 */ 110 public Object newInstance(int var1, Object[] var2) throws InvocationTargetException { 111 190a8bdd var10000 = new 190a8bdd; 112 190a8bdd var10001 = var10000; 113 int var10002 = var1; 114 115 try { 116 switch(var10002) { 117 case 0: 118 //构造器是0个参数,表示通过无参构造器创建对象 119 var10001.<init>(); 120 return var10000; 121 } 122 } catch (Throwable var3) { 123 throw new InvocationTargetException(var3); 124 } 125 126 throw new IllegalArgumentException("Cannot find matching method/constructor"); 127 } 128 129 /** 130 * Returns the maximum method index for this class. 131 */ 132 public int getMaxIndex() { 133 return 20; 134 } 135}

可以看到,对于proxy.invokeSuper()的调用,实际上调用了fci.f2.invoke(fci.i2, obj, args)。而fci.i2 = fci.f2.getIndex(sig2); 注意这里的sig2是指CGLIB$sayHello$0()这个方法,即代理对象中用于调用目标对象sayHello()的方法

所以整个调用流程为:

1.通过sayHello()的方法签名,在代理类的FastClass中找到**CGLIB$sayHello$0()**方法的索引。

2.调用fci.f2.invoke()方法,因此直接调用代理对象的**CGLIB$sayHello$0()**方法,于是间接调用到了Hello.sayHello()方法,输出了下面这句:

Hello Doris

最后继续在MyMethodInterceptor中输出了

>>>> After method invocation

【全文完】

=========================分隔线=====================================

参考:https://zhuanlan.zhihu.com/p/106069224

=========================分隔线=====================================

源码:https://github.com/wanxiaolong/JavaProxyDemo

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

  代理模式是一种很常见的模式,本文主要分析cglib动态代理的过程1\.举例使用cglib代理需要引入两个包,maven的话包引入如下<!https://mvnrepository.com/artifact/cglib/cglib<dependency

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

CGLIB动态代理源码分析 - HelloWorld