前面介绍到MethodProxy对象,表示一个方法的代理,比如UserSerivce中的test()方法,在对应的代理类中会有对应的两个方法:
public class UserInterface$$EnhancerByCGLIB$$20ecfdd implements UserInterface, Factory {final void CGLIB$test$4() {super.test();}public final void test() {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$test$4$Method, CGLIB$emptyArgs, CGLIB$test$4$Proxy);} else {super.test();}}}
而MethodProxy对象代理就是这两个方法,比如:
// 表示执行某个对象的CGLIB$test$0()方法,如果o中没有CGLIB$test$0()方法则会报错methodProxy.invokeSuper(o, args)// 表示执行某个对象的test方法methodProxy.invoke(o, args)
我们先来看一下MethodProxy对象的创建,创建的入口在代理类中:
CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$0");
对应的方法为:
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {// c1是UserService类// c2是UserService代理类// desc是方法的返回类型 ()V// name1是方法名 test// name2是代理类中对应的另外一个方法名,CGLIB$test$0MethodProxy proxy = new MethodProxy();proxy.sig1 = new Signature(name1, desc);proxy.sig2 = new Signature(name2, desc);proxy.createInfo = new CreateInfo(c1, c2);return proxy;}
可以发现MethodProxy对象中主要有三个属性:
- sig1,表示test方法
- sig2,表示CGLIB$test$0方法
- createInfo,表示UserService类和UserService代理类
我们再来看MethodProxy的invoke()和invokeSuper()方法:
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;}}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();}}
我们可以发现,这两个方法差不多,首先都需要用到一个FastClassInfo对象,这个对象是在init()方法构造的。
private void init() {if (fastClassInfo == null) {synchronized (initLock) {if (fastClassInfo == null) {CreateInfo ci = createInfo;FastClassInfo fci = new FastClassInfo();fci.f1 = helper(ci, ci.c1);fci.f2 = helper(ci, ci.c2);fci.i1 = fci.f1.getIndex(sig1);fci.i2 = fci.f2.getIndex(sig2);fastClassInfo = fci;createInfo = null;}}}}
FastClassInfo对象中主要有四个属性:
- f1,UserService类对应的一个FastClass代理对象
- f2,UserService代理类对应的一个FastClass代理对象
- i1,test方法在UserService类对应的一个FastClass代理对象中的下标
- i2,CGLIB$test$0方法在UserService代理对对应的一个FastClass代理对象
我们可以看到这里应该将会产生两个FastClass代理类
以下是UserService所对应的FastClass代理类,继承了FastClass
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.zhouyu;import java.lang.reflect.InvocationTargetException;import net.sf.cglib.core.Signature;import net.sf.cglib.reflect.FastClass;public class UserService$$FastClassByCGLIB$$4fef7899 extends FastClass {public UserService$$FastClassByCGLIB$$4fef7899(Class var1) {super(var1);}public int getIndex(Signature var1) {String var10000 = var1.toString();switch(var10000.hashCode()) {case -1422510685:if (var10000.equals("test()V")) {return 0;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 1;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 2;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 3;}}return -1;}public int getIndex(String var1, Class[] var2) {switch(var1.hashCode()) {case -1776922004:if (var1.equals("toString")) {switch(var2.length) {case 0:return 2;}}break;case -1295482945:if (var1.equals("equals")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 1;}}}break;case 3556498:if (var1.equals("test")) {switch(var2.length) {case 0:return 0;}}break;case 147696667:if (var1.equals("hashCode")) {switch(var2.length) {case 0:return 3;}}}return -1;}public int getIndex(Class[] var1) {switch(var1.length) {case 0:return 0;default:return -1;}}public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {UserService var10000 = (UserService)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.test();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");}public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {UserService var10000 = new UserService;UserService var10001 = var10000;int var10002 = var1;try {switch(var10002) {case 0:var10001.<init>();return var10000;}} catch (Throwable var3) {throw new InvocationTargetException(var3);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public int getMaxIndex() {return 3;}}
以下是UserService代理类所对应的FastClass代理类,继承了FastClass
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.zhouyu;import com.zhouyu.UserService..EnhancerByCGLIB..4d890297;import java.lang.reflect.InvocationTargetException;import net.sf.cglib.core.Signature;import net.sf.cglib.proxy.Callback;import net.sf.cglib.reflect.FastClass;public class UserService$$EnhancerByCGLIB$$4d890297$$FastClassByCGLIB$$6ea3bb5e extends FastClass {public UserService$$EnhancerByCGLIB$$4d890297$$FastClassByCGLIB$$6ea3bb5e(Class var1) {super(var1);}public int getIndex(Signature var1) {String var10000 = var1.toString();switch(var10000.hashCode()) {case -2055565910:if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {return 4;}break;case -1882565338:if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {return 9;}break;case -1659809612:if (var10000.equals("CGLIB$test$0()V")) {return 8;}break;case -1457535688:if (var10000.equals("CGLIB$STATICHOOK1()V")) {return 7;}break;case -1422510685:if (var10000.equals("test()V")) {return 20;}break;case -1411842725:if (var10000.equals("CGLIB$hashCode$3()I")) {return 11;}break;case -894172689:if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 18;}break;case -623122092:if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {return 6;}break;case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return 16;}break;case -419626537:if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {return 1;}break;case 560567118:if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {return 0;}break;case 811063227:if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 19;}break;case 973717575:if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {return 2;}break;case 1221173700:if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 17;}break;case 1230699260:if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {return 3;}break;case 1306468936:if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {return 10;}break;case 1584330438:if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {return 5;}break;case 1800494055:if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {return 12;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 13;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 14;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 15;}}return -1;}public int getIndex(String var1, Class[] var2) {switch(var1.hashCode()) {case -1776922004:if (var1.equals("toString")) {switch(var2.length) {case 0:return 14;}}break;case -1295482945:if (var1.equals("equals")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 13;}}}break;case -1053468136:if (var1.equals("getCallbacks")) {switch(var2.length) {case 0:return 2;}}break;case -124978609:if (var1.equals("CGLIB$equals$1")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 9;}}}break;case -60403779:if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {switch(var2.length) {case 1:if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 5;}}}break;case -29025555:if (var1.equals("CGLIB$hashCode$3")) {switch(var2.length) {case 0:return 11;}}break;case 3556498:if (var1.equals("test")) {switch(var2.length) {case 0:return 20;}}break;case 85179481:if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {switch(var2.length) {case 1:if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 4;}}}break;case 94756189:if (var1.equals("clone")) {switch(var2.length) {case 0:return 16;}}break;case 147696667:if (var1.equals("hashCode")) {switch(var2.length) {case 0:return 15;}}break;case 161998109:if (var1.equals("CGLIB$STATICHOOK1")) {switch(var2.length) {case 0:return 7;}}break;case 495524492:if (var1.equals("setCallbacks")) {switch(var2.length) {case 1:if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 1;}}}break;case 543320865:if (var1.equals("CGLIB$test$0")) {switch(var2.length) {case 0:return 8;}}break;case 1154623345:if (var1.equals("CGLIB$findMethodProxy")) {switch(var2.length) {case 1:if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {return 6;}}}break;case 1543336189:if (var1.equals("CGLIB$toString$2")) {switch(var2.length) {case 0:return 10;}}break;case 1811874389:if (var1.equals("newInstance")) {switch(var2.length) {case 1:String var10001 = var2[0].getName();switch(var10001.hashCode()) {case -845341380:if (var10001.equals("net.sf.cglib.proxy.Callback")) {return 18;}break;case 1730110032:if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {return 17;}}case 2:default:break;case 3:if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 19;}}}break;case 1817099975:if (var1.equals("setCallback")) {switch(var2.length) {case 2:if (var2[0].getName().equals("int") && var2[1].getName().equals("net.sf.cglib.proxy.Callback")) {return 0;}}}break;case 1905679803:if (var1.equals("getCallback")) {switch(var2.length) {case 1:if (var2[0].getName().equals("int")) {return 3;}}}break;case 1951977610:if (var1.equals("CGLIB$clone$4")) {switch(var2.length) {case 0:return 12;}}}return -1;}public int getIndex(Class[] var1) {switch(var1.length) {case 0:return 0;default:return -1;}}public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {4d890297 var10000 = (4d890297)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);return null;case 1:var10000.setCallbacks((Callback[])var3[0]);return null;case 2:return var10000.getCallbacks();case 3:return var10000.getCallback(((Number)var3[0]).intValue());case 4:4d890297.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);return null;case 5:4d890297.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);return null;case 6:return 4d890297.CGLIB$findMethodProxy((Signature)var3[0]);case 7:4d890297.CGLIB$STATICHOOK1();return null;case 8:var10000.CGLIB$test$0();return null;case 9:return new Boolean(var10000.CGLIB$equals$1(var3[0]));case 10:return var10000.CGLIB$toString$2();case 11:return new Integer(var10000.CGLIB$hashCode$3());case 12:return var10000.CGLIB$clone$4();case 13:return new Boolean(var10000.equals(var3[0]));case 14:return var10000.toString();case 15:return new Integer(var10000.hashCode());case 16:return var10000.clone();case 17:return var10000.newInstance((Callback[])var3[0]);case 18:return var10000.newInstance((Callback)var3[0]);case 19:return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);case 20:var10000.test();return null;}} catch (Throwable var4) {throw new InvocationTargetException(var4);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {4d890297 var10000 = new 4d890297;4d890297 var10001 = var10000;int var10002 = var1;try {switch(var10002) {case 0:var10001.<init>();return var10000;}} catch (Throwable var3) {throw new InvocationTargetException(var3);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public int getMaxIndex() {return 20;}}
其实这两个类类似,都是针对某一个类的FastClass代理类,所以我们好好看一下UserService所对应的FastClass,该类主要有:
- 一个构造方法
- public int getIndex(Signature var1)
- public int getIndex(String var1, Class[] var2)
- public int getIndex(Class[] var1)
- public Object invoke(int var1, Object var2, Object[] var3)
- public Object newInstance(int var1, Object[] var2)
- public int getMaxIndex()
顾名思义,FastClass的作用是提高方法的执行速度,按照正常的实现,当我们调用MethodProxy对象的invoke()或invokeSuper()方法时,首先应该要做到的就是找到对应的Method对象,比如:
- 执行invoke(),要找到test方法对应的Method对象
- 执行invokeSuper(),要找到CGLIB$test$0()方法对应的Method对象
然后利用反射来执行Method。
那么FastClass的机制就是预先把UserService类或UserService代理类中的所有方法做一个索引,比如:
public int getIndex(Signature var1) {String var10000 = var1.toString();switch(var10000.hashCode()) {case -1422510685:if (var10000.equals("test()V")) {return 0;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 1;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 2;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 3;}}return -1;}
一旦调了这个方法,就会得到当前要执行的方法所对应的index,比如test()对应的index为0
我们再来看init()方法:
private void init() {if (fastClassInfo == null) {synchronized (initLock) {if (fastClassInfo == null) {CreateInfo ci = createInfo;FastClassInfo fci = new FastClassInfo();fci.f1 = helper(ci, ci.c1);fci.f2 = helper(ci, ci.c2);fci.i1 = fci.f1.getIndex(sig1);fci.i2 = fci.f2.getIndex(sig2);fastClassInfo = fci;createInfo = null;}}}}
两个helper()方法就是分别去生成UserService类和UserService代理类所对应的FastClass代理类。
接下来的两个getIndex(),就是分别去:
- 去UserService类对应的FastClass代理类中找到test()方法的下标i1
- 去UserService代理类对应的FastClass代理类中找到CGLIB$test$0()方法的下标i2
然后把两个下标都记录在fastClassInfo中。
紧接着就会去执行:
- invoke:fci.f1.invoke(fci.i1, obj, args),执行UserService类对应的FastClass代理类的invoke方法
- invokeSuper:fci.f2.invoke(fci.i2, obj, args),执行UserService代理类对应的FastClass代理类的invoke方法
比如UserService类对应的FastClass代理类的invoke方法的代码为:
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {UserService var10000 = (UserService)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.test();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");}
我们可以发现代码还是比较简单的,比如如果传入的下标是0,那么就会执行var2的test();
对于UserService代理类对应的FastClass代理类也类似:
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {4d890297 var10000 = (4d890297)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);return null;case 1:var10000.setCallbacks((Callback[])var3[0]);return null;case 2:return var10000.getCallbacks();case 3:return var10000.getCallback(((Number)var3[0]).intValue());case 4:4d890297.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);return null;case 5:4d890297.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);return null;case 6:return 4d890297.CGLIB$findMethodProxy((Signature)var3[0]);case 7:4d890297.CGLIB$STATICHOOK1();return null;case 8:var10000.CGLIB$test$0();return null;case 9:return new Boolean(var10000.CGLIB$equals$1(var3[0]));case 10:return var10000.CGLIB$toString$2();case 11:return new Integer(var10000.CGLIB$hashCode$3());case 12:return var10000.CGLIB$clone$4();case 13:return new Boolean(var10000.equals(var3[0]));case 14:return var10000.toString();case 15:return new Integer(var10000.hashCode());case 16:return var10000.clone();case 17:return var10000.newInstance((Callback[])var3[0]);case 18:return var10000.newInstance((Callback)var3[0]);case 19:return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);case 20:var10000.test();return null;}} catch (Throwable var4) {throw new InvocationTargetException(var4);}throw new IllegalArgumentException("Cannot find matching method/constructor");}
比如下标为8,就会执行var10000.CGLIB$test$0();
比如下标为20,就会执行var10000.test();
而var10000,是所传入对象强制转化为4d890297类的对象,4d890297其实就是UserService的代理类。
所以我们可以发现,当执行invokeSuper()这个方法时,不能传入UserService对象,只能传入UserService的代理对象,不然就不能转换成为UserService代理类类型。
所以FastClass,快的地方就是预先把方法信息都生成好了,在真正调用的时候,不用再去找Method对象,而是直接就执行方法了。
