在intercept()方法中执行MethodProxy的invokeSuper方法:
public Object invokeSuper(Object obj, Object[] args) throws Throwable { try { // 调用init方法,获取下标,且要生成FastClass类实例 init(); FastClassInfo fci = fastClassInfo; // f2是被代理类的FastClass实例,下标在init方法中计算好了 // 假设我们调用的上面的toString()方法,其实也就是调用的代理类的CGLIB$toString$0方法,这样就实现了原始方法的调用,所以我们才需要执行invokeSuper,如果调用invoke,就会形成死循环 return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } /** * invoke执行的是原始类的方法,因为f1是被代理类的FastClass * */ public Object invoke(Object obj, Object[] args) throws Throwable { try { init(); FastClassInfo fci = fastClassInfo; 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; } }
看下被代理类的fastClass的invoke方法():
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { 558ee7c6 var10000 = (558ee7c6)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((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]); case 6: return var10000.newInstance((Callback)var3[0]); case 7: var10000.setCallbacks((Callback[])var3[0]); return null; case 8: var10000.findLove(); return null; case 9: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 10: return var10000.getCallback(((Number)var3[0]).intValue()); case 11: return var10000.getCallbacks(); case 12: 558ee7c6.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 13: 558ee7c6.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 14: return 558ee7c6.CGLIB$findMethodProxy((Signature)var3[0]); case 15: return new Boolean(var10000.CGLIB$equals$1(var3[0])); case 16: return var10000.CGLIB$toString$2(); case 17: var10000.CGLIB$findLove$0(); return null; case 18: return var10000.CGLIB$clone$4(); case 19: return new Integer(var10000.CGLIB$hashCode$3()); case 20: 558ee7c6.CGLIB$STATICHOOK1(); return null; } } catch (Throwable var4) { throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); }
最终调到了 ,被代理类的findLove()方法。
cglib这里有点复杂,重新梳理下:
CglibTest
进入到代理类中调用findLove()方法:
Customer$$EnhancerByCGLIB$$558ee7c6
调用的时候会,如果媒婆类CGlibMeipo,写了拦截方法,所以会跳到intercept()
CGlibMeipo
执行完before,开始调动methodProxy的invokeSuper方法,
MethodProxy
//f1;com.example.proxy.staticproxy.Son //f2.com.example.proxy.staticproxy.Son$$EnhancerByCGLIB$$d760ccc
继续走代理类的代理类的
fastClasscom.example.proxy.staticproxy.Son$$EnhancerByCGLIB$$d760ccc的invoke
方法:
com.example.proxy.staticproxy.Son$$EnhancerByCGLIB$$d760ccc
到了这里又返回到了代理类Son$$EnhancerByCGLIB$$d760ccc中,开始执行 CGLIB$findLove$0()方法:
代理类: Son$$EnhancerByCGLIB$$d760ccc
该类继承了Son,所以走Son里面的finidLove方法:
Son
执行完返回到媒婆动态代理类的after()方法:
CGlibMeipo
到此就执行完了,返回到了测试类中:
CglibTest
自此,cglib动态创建代理对象就调试完了。
下面开始总结下:
五.jdk和cglib各自怎么调用被代理对象的方法?
1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
2.JDK 和CGLib 都是在运行期生成字节码,JDK 是直接写Class 字节码,CGLib 使用ASM
框架写Class 字节码,Cglib 代理实现更复杂,生成代理类比JDK 效率低。
3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过FastClass 机制直接调用方法,CGLib 执行效率更高。
六.cglib动态生成的代理对象的时候为什么是3个class?
首先cglib需要创建一个代理对象,这是必然的,多出来的2个class文件,是因为cglib没有使用反射,而是使用fastclass维护每个方法的索引。一个类保存代理对象的方法索引,一个保存被代理对象的索引。这样当客户端调用的时候,fastclass机制就提供给客户端相应的方法区执行。所以是3个class。