前言
CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。生成的代理类会继承被代理类,并重载其所有的方法。使用Cglib代理会生成三个代理类,继承目标类的代理类、继承FastClass的目标类、继承FastClss的代理类。
正文
我们要想了解其原理,先从生成的代理文件入手,看其结构特点。
测试用例
编写目标类(被代理类)
public class Book { public void read(){ System.out.println("read"); }}
自定义方法拦截器
public class MyCglib implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("增强"); Object o1 = methodProxy.invokeSuper(o, objects); return o1; }}
public class CglibTest { public static void main(String[] args) { //指定代理文件生成位置 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:"); //通过Cglib Enhancer enhancer=new Enhancer(); //设置父类类型 enhancer.setSuperclass(Book.class); //设置回调接口 enhancer.setCallback(new MyCglib()); Book o = (Book) enhancer.create(); o.read(); }}
结果分析
运行以上测试用例后,查看生成的类目录,可以看到生成了3个.class字节码代理文件。 代理类:
import java.lang.reflect.Method;import org.springframework.cglib.core.ReflectUtils;import org.springframework.cglib.core.Signature;import org.springframework.cglib.proxy.Callback;import org.springframework.cglib.proxy.Factory;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;public class Book$$EnhancerByCGLIB$$7c19c0f5 extends Book 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$read$0$Method; private static final MethodProxy CGLIB$read$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("proxy.cglib.Book$$EnhancerByCGLIB$$7c19c0f5"); 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$read$0$Method = ReflectUtils.findMethods(new String[]{"read", "()V"}, (var1 = Class.forName("proxy.cglib.Book")).getDeclaredMethods())[0]; CGLIB$read$0$Proxy = MethodProxy.create(var1, var0, "()V", "read", "CGLIB$read$0"); } final void CGLIB$read$0() { super.read(); } public final void read() { 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$read$0$Method, CGLIB$emptyArgs, CGLIB$read$0$Proxy); } else { super.read(); } } 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 1080349215: if (var10000.equals("read()V")) { return CGLIB$read$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 Book$$EnhancerByCGLIB$$7c19c0f5() { 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) { Book$$EnhancerByCGLIB$$7c19c0f5 var1 = (Book$$EnhancerByCGLIB$$7c19c0f5)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); Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5; 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(); }}
目标类FastClass:
import java.lang.reflect.InvocationTargetException;import org.springframework.cglib.core.Signature;import org.springframework.cglib.reflect.FastClass;public class Book$$FastClassByCGLIB$$236a9cb6 extends FastClass { public Book$$FastClassByCGLIB$$236a9cb6(Class var1) { super(var1); } public int getIndex(Signature var1) { String var10000 = var1.toString(); switch(var10000.hashCode()) { case 1080349215: if (var10000.equals("read()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 3496342: if (var1.equals("read")) { 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 { Book var10000 = (Book)var2; int var10001 = var1; try { switch(var10001) { case 0: var10000.read(); 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 { Book var10000 = new Book; Book 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; }}
代理类FastClass:
import java.lang.reflect.InvocationTargetException;import org.springframework.cglib.core.Signature;import org.springframework.cglib.proxy.Callback;import org.springframework.cglib.reflect.FastClass;import proxy.cglib.Book..EnhancerByCGLIB..7c19c0f5;public class Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900 extends FastClass { public Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900(Class var1) { super(var1); } public int getIndex(Signature var1) { String var10000 = var1.toString(); switch(var10000.hashCode()) { case -1882565338: if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) { return 18; } break; case -1870561232: if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) { return 14; } break; case -1745842178: if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) { return 9; } break; case -1641413109: if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 4; } break; case -1593131472: if (var10000.equals("CGLIB$read$0()V")) { return 20; } break; case -1457535688: if (var10000.equals("CGLIB$STATICHOOK1()V")) { return 15; } break; case -1411842725: if (var10000.equals("CGLIB$hashCode$3()I")) { return 19; } break; case -1034266769: if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) { return 13; } break; case -1025895669: if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) { return 12; } break; case -988317324: if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 5; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return 3; } break; case 610042816: if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 6; } break; case 1080349215: if (var10000.equals("read()V")) { return 7; } break; case 1132856532: if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) { return 10; } break; case 1246779367: if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) { return 8; } break; case 1306468936: if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) { return 16; } break; case 1364367423: if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) { return 11; } break; case 1800494055: if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) { return 17; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return 0; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return 1; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return 2; } } return -1; } public int getIndex(String var1, Class[] var2) { switch(var1.hashCode()) { case -1776922004: if (var1.equals("toString")) { switch(var2.length) { case 0: return 1; } } break; case -1295482945: if (var1.equals("equals")) { switch(var2.length) { case 1: if (var2[0].getName().equals("java.lang.Object")) { return 0; } } } break; case -1053468136: if (var1.equals("getCallbacks")) { switch(var2.length) { case 0: return 10; } } break; case -124978609: if (var1.equals("CGLIB$equals$1")) { switch(var2.length) { case 1: if (var2[0].getName().equals("java.lang.Object")) { return 18; } } } break; case -60403779: if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) { switch(var2.length) { case 1: if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) { return 13; } } } break; case -29025555: if (var1.equals("CGLIB$hashCode$3")) { switch(var2.length) { case 0: return 19; } } break; case 3496342: if (var1.equals("read")) { switch(var2.length) { case 0: return 7; } } break; case 85179481: if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) { switch(var2.length) { case 1: if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) { return 12; } } } break; case 94756189: if (var1.equals("clone")) { switch(var2.length) { case 0: return 3; } } break; case 147696667: if (var1.equals("hashCode")) { switch(var2.length) { case 0: return 2; } } break; case 161998109: if (var1.equals("CGLIB$STATICHOOK1")) { switch(var2.length) { case 0: return 15; } } break; case 485510949: if (var1.equals("CGLIB$read$0")) { switch(var2.length) { case 0: return 20; } } break; case 495524492: if (var1.equals("setCallbacks")) { switch(var2.length) { case 1: if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) { return 9; } } } break; case 1154623345: if (var1.equals("CGLIB$findMethodProxy")) { switch(var2.length) { case 1: if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) { return 14; } } } break; case 1543336189: if (var1.equals("CGLIB$toString$2")) { switch(var2.length) { case 0: return 16; } } break; case 1811874389: if (var1.equals("newInstance")) { switch(var2.length) { case 1: String var10001 = var2[0].getName(); switch(var10001.hashCode()) { case -1997738671: if (var10001.equals("[Lorg.springframework.cglib.proxy.Callback;")) { return 4; } break; case 1364160985: if (var10001.equals("org.springframework.cglib.proxy.Callback")) { return 6; } } 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("[Lorg.springframework.cglib.proxy.Callback;")) { return 5; } } } break; case 1817099975: if (var1.equals("setCallback")) { switch(var2.length) { case 2: if (var2[0].getName().equals("int") && var2[1].getName().equals("org.springframework.cglib.proxy.Callback")) { return 8; } } } break; case 1905679803: if (var1.equals("getCallback")) { switch(var2.length) { case 1: if (var2[0].getName().equals("int")) { return 11; } } } break; case 1951977610: if (var1.equals("CGLIB$clone$4")) { switch(var2.length) { case 0: return 17; } } } 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 { 7c19c0f5 var10000 = (7c19c0f5)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.read(); return null; case 8: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 9: var10000.setCallbacks((Callback[])var3[0]); return null; case 10: return var10000.getCallbacks(); case 11: return var10000.getCallback(((Number)var3[0]).intValue()); case 12: 7c19c0f5.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 13: 7c19c0f5.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 14: return 7c19c0f5.CGLIB$findMethodProxy((Signature)var3[0]); case 15: 7c19c0f5.CGLIB$STATICHOOK1(); return null; case 16: return var10000.CGLIB$toString$2(); case 17: return var10000.CGLIB$clone$4(); case 18: return new Boolean(var10000.CGLIB$equals$1(var3[0])); case 19: return new Integer(var10000.CGLIB$hashCode$3()); case 20: var10000.CGLIB$read$0(); 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 { 7c19c0f5 var10000 = new 7c19c0f5; 7c19c0f5 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; }}
1、我们可以看到代理类中拥有被代理类的所有的方法,在代理类被实例化后后执行静态代码块的内容,会对被代理类的每个方法进行解析,计算出代理类和被代理类方法名称的Signature值,并封装成MethodProxy对象; 创建MethodProxy过程见方法1详解 创建代理类过程见方法4详解
2、在代理类的方法里面会调用我们自定义的方法拦截器,并把代理类对象、方法名称解析对应的MethodProxy、方法对象传递进去,最终由自定义方法拦截器来调用。
3、自定义方法拦截器中的intercept方法,我们可以根据传递进来的MethodProxy决定调用逻辑,如MethodProxy的invokeSuper会调用父类方法。
4、MethodProxy的invokeSuper方法(见方法2详解)会传递代理类对象及其要执行对应方法参数。invokeSuper流程中会生成继承FastClass的被代理类跟代理类共两个.class文件。其中有两个重要的方法getIndex和invoke方法;
5、getIndex方法会根据步骤1中方法名计算出Signature来匹配方法对应的key,根据key去匹配invoke方法决定最终调用哪个方法。这个步骤没有涉及反射也是与JDK动态代理不同的地方。
方法1:MethodProxy类的create方法
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) { MethodProxy proxy = new MethodProxy(); //计算的是被代理类的 proxy.sig1 = new Signature(name1, desc); //计算的是代理类的 proxy.sig2 = new Signature(name2, desc); proxy.createInfo = new CreateInfo(c1, c2); return proxy; }
方法2:MethodProxy类的invoke方法
MethodProxy
public Object invokeSuper(Object obj, Object[] args) throws Throwable { try { //这个过程会创建类型为代理类跟被代理的FastClass类 init(); //获取init中封装好的信息 FastClassInfo fci = fastClassInfo; //调用被代理类的方法,传递方法index下标,通过该下标会在FastClass找出对应的方法并执行 return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } catch (IllegalArgumentException ex) { if (fastClassInfo.i1 < 0) throw new IllegalArgumentException("Protected method: " + sig1); throw ex; } }
init(),见方法3详解
方法3:MethodProxy类的init方法
private void init() {
/*
* Using a volatile invariant allows us to initialize the FastClass and
* method index pairs atomically.
*
* Double-checked locking is safe with volatile in Java 5. Before 1.5 this
* code could allow fastClassInfo to be instantiated more than once, which
* appears to be benign.
*/
if (fastClassInfo == null) {
synchronized (initLock) {
//判断是否缓存过
if (fastClassInfo == null) {
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
//生成被代理类的FastClass对象
fci.f1 = helper(ci, ci.c1);
//生成代理类的FastClass对象
fci.f2 = helper(ci, ci.c2);
//根据sig值计算出该方法名在被代理类FastClass中对应的下标
fci.i1 = fci.f1.getIndex(sig1);
//根据sig值计算出该方法名在代理类FastClass中对应的下标
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
生成FastClass对象的过程跟生成代理类过程有点类似,这里不做讲解,后面会讲解代理类的创建过程,过程都差不多。
方法4:enhancer.create方法
代理类会在我们测试用例中调用enhancer.create()方法时进行创建。
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
//校验callbackTypes、filter是否为空,以及为空时的处理
preValidate();
//通过newInstance方法来创建EnhancerKey对象.KEY_FACTORY对象在测试用例new Enhance流程中会被动态代理创建
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;
}
super.create(key),见方法5详解
方法5:create
protected Object create(Object key) {
try {
//获取类加载器
ClassLoader loader = getClassLoader();
//尝试从缓存中获取当前类加载器对应的ClassLoaderData对象
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) {
//创建ClassLoaderData并加入newCache缓存中
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
//生成代理对象
Object obj = data.get(this, getUseCache());
//如果类似是Class对象,则进行实例化
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
}
new ClassLoaderData(loader),见方法6详解
data.get(this, getUseCache()),见方法7详解
方法6:new ClassLoaderData(loader)
这个类比较长,这里我就把比较重要的两个方法进行讲解,这里
protected static class ClassLoaderData {
private final Set<String> reservedClassNames = new HashSet<String>();
/**
* {@link AbstractClassGenerator} here holds "cache key" (e.g. {@link org.springframework.cglib.proxy.Enhancer}
* configuration), and the value is the generated class plus some additional values
* (see {@link #unwrapCachedValue(Object)}.
* <p>The generated classes can be reused as long as their classloader is reachable.</p>
* <p>Note: the only way to access a class is to find it through generatedClasses cache, thus
* the key should not expire as long as the class itself is alive (its classloader is alive).</p>
*/
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
/**
* Note: ClassLoaderData object is stored as a value of {@code WeakHashMap<ClassLoader, ...>} thus
* this classLoader reference should be weak otherwise it would make classLoader strongly reachable
* and alive forever.
* Reference queue is not required since the cleanup is handled by {@link WeakHashMap}.
*/
private final WeakReference<ClassLoader> classLoader;
private final Predicate uniqueNamePredicate = new Predicate() {
public boolean evaluate(Object name) {
return reservedClassNames.contains(name);
}
};
//这里存的是Function函数,后续步骤中会调用
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference<ClassLoader>(classLoader);
//这里创建的是函数式接口,后续步骤中会调用
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
//创建代理类
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
public ClassLoader getClassLoader() {
return classLoader.get();
}
public void reserveName(String name) {
reservedClassNames.add(name);
}
public Predicate getUniqueNamePredicate() {
return uniqueNamePredicate;
}
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
return gen.generate(ClassLoaderData.this);
}
else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
}
方法7:get
public Object get(AbstractClassGenerator gen, boolean useCache) {
//如果没有使用缓存,则直接调用创建代理类方法
if (!useCache) {
return gen.generate(ClassLoaderData.this);
}
else {
//这里会调用方法6中创建的两个Function函数式类
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
public V get(K key) {
//调用步骤6中GET_KEY函数式类
KK cacheKey = this.keyMapper.apply(key);
//尝试从缓存中获取代理类对象
Object v = this.map.get(cacheKey);
//如果获取不到则创建代理类
return v != null && !(v instanceof FutureTask) ? v : this.createEntry(key, cacheKey, v);
}
this.createEntry(key, cacheKey, v),见方法8详解
方法8:createEntry
protected V createEntry(final K key, KK cacheKey, Object v) {
boolean creator = false;
FutureTask task;
Object result;
if (v != null) {
task = (FutureTask)v;
} else {
//创建线程
task = new FutureTask(new Callable<V>() {
public V call() throws Exception {
//调用方法6中写好的Function函数
return LoadingCache.this.loader.apply(key);
}
});
//将线程加入缓存中
result = this.map.putIfAbsent(cacheKey, task);
if (result == null) {
creator = true;
//开启线程
task.run();
} else {
if (!(result instanceof FutureTask)) {
return result;
}
task = (FutureTask)result;
}
}
try {
result = task.get();
} catch (InterruptedException var9) {
throw new IllegalStateException("Interrupted while loading cache item", var9);
} catch (ExecutionException var10) {
Throwable cause = var10.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
throw new IllegalStateException("Unable to load cache item", cause);
}
if (creator) {
this.map.put(cacheKey, result);
}
return result;
}
LoadingCache.this.loader.apply(key),见方法9详解
方法9:apply
调用函数式接口
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
protected Class generate(ClassLoaderData data) {
validate();
//设置代理类名称前缀
if (superclass != null) {
setNamePrefix(superclass.getName());
}
else if (interfaces != null) {
setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
}
return super.generate(data);
}
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
}
}
//生成代理类字节码流
byte[] b = strategy.generate(this);
//获取字节码代表的代理类名称
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
// SPRING PATCH BEGIN
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
// SPRING PATCH END
}
return gen;
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
finally {
CURRENT.set(save);
}
}
strategy.generate(this),见方法10详解
方法10:generate
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = this.getClassVisitor();
this.transform(cg).generateClass(cw);
return this.transform(cw.toByteArray());
}
public void generateClass(ClassVisitor v) throws Exception {
//如果目标类存在则以目标类为父类,否则以Object为父类
Class sc = (superclass == null) ? Object.class : superclass;
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
//获取父类的所有构造函数
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
//去掉private不能被继承的构造函数
filterConstructors(sc, constructors);
// Order is very important: must add superclass, then
// its superclass chain, then each interface and
// its superinterfaces.
//存放代理类的所有方法
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
//获取其父类的所有方法,包括父类的父类... 父类的所有接口包含的方法,过滤掉不能被继承的方法
getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
//所有方法进行修饰符处理
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method) value;
int modifiers = Constants.ACC_FINAL
| (method.getModifiers()
& ~Constants.ACC_ABSTRACT
& ~Constants.ACC_NATIVE
& ~Constants.ACC_SYNCHRONIZED);
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
//创建写日期
ClassEmitter e = new ClassEmitter(v);
if (currentData == null) {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
Type.getType(sc),
(useFactory ?
TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
TypeUtils.getTypes(interfaces)),
Constants.SOURCE_FILE);
}
else {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
null,
new Type[]{FACTORY},
Constants.SOURCE_FILE);
}
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
if (!interceptDuringConstruction) {
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
}
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
if (serialVersionUID != null) {
e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
for (int i = 0; i < callbackTypes.length; i++) {
e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
}
// This is declared private to avoid "public field" pollution
e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
if (currentData == null) {
//写入方法
emitMethods(e, methods, actualMethods);
//写入构造方法
emitConstructors(e, constructorInfo);
}
else {
emitDefaultConstructor(e);
}
//写入回调方法
emitSetThreadCallbacks(e);
//写入静态代理块
emitSetStaticCallbacks(e);
//绑定回调方法
emitBindCallbacks(e);
if (useFactory || currentData != null) {
int[] keys = getCallbackKeys();
emitNewInstanceCallbacks(e);
emitNewInstanceCallback(e);
emitNewInstanceMultiarg(e, constructorInfo);
emitGetCallback(e, keys);
emitSetCallback(e, keys);
emitGetCallbacks(e);
emitSetCallbacks(e);
}
e.end_class();
}
到这里整个代理类创建过程就差不多告一段落了。
总结
Cglib动态代理不需要被代理类实现接口,根据原理我们知道生成的代理类是继承了被代理类,而且其方法调用方法是使用FastClass,这与JDK动态代理的反射有比较大的区别。
JDK和CGLIB动态代理的区别:
-
JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
-
CGLIB代理使用字节码处理框架ASM,对代理对象类的class文件加载进来,通过修改字节码生成子类。
-
JDK创建代理对象效率较高,执行效率较低;
-
CGLIB创建代理对象效率较低,执行效率高。
-
JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
-
CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不- 能代理final修饰的类。
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
-
实现InvocationHandler接口,重写invoke()
-
使用Proxy.newProxyInstance()产生代理对象
-
被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
-
实现MethodInterceptor接口,重写intercept()
-
使用Enhancer对象.create()产生代理对象
本文转自 blog.csdn.net/weixin_4503…,如有侵权,请联系删除。