一、前言
最近在探索Spring AOP的性能,发现最初是绕不开JDK动静代理和CGLIB动静代理这两个点。笔者心里大抵有这么个概念:对于动静代理来说,CGLIB性能要好于JDK。也晓得CGLIB是利用ASM技术基于继承子类实现动静代理,JDK是基于实现接口实现动静代理,然而对于底层实现还是比拟含糊。明天就彻底整明确CGLIB动静代理的底层实现。
二、前置筹备
(一)测试代码
CGLIB外围的几个概念:
- 被代理对象,本案例【Dog】
- 办法拦截器MethodInterceptor,本案例【CglibMethodInterceptor】
- Enhance代理对象生成工具,本案例【TestMain测试主类中创立】
1. 自定义办法拦截器CglibMethodInterceptor
前面也会将MethodInterceptor
说成Callback
,其实是一个货色,MethodInterceptor
是实现了Callback
接口的。
/** * 办法拦截器,不必依赖被代理业务类的援用 */public class CglibMethodInterceptor implements MethodInterceptor { /** * 性能次要是在调用业务类办法之前 之后增加统计工夫的办法逻辑. * intercept 因为具备 MethodProxy methodProxy 参数的起因,不再须要代理类的援用对象了,间接通过 methodProxy 对象拜访被代理对象的办法(这种形式更快)。 * 当然 也能够通过反射机制,通过 method 援用实例 Object result = method.invoke(target, args); 模式反射调用被代理类办法, * target 实例代表被代理类对象援用, 初始化 CglibMethodInterceptor 时候被赋值 。然而Cglib不举荐应用这种形式 * * @param object 代表Cglib 生成的动静代理类 对象自身 * @param method 代理类中被拦挡的接口办法 Method 实例 * @param args 接口办法参数 * @param methodProxy 用于调用父类真正的业务类办法。能够间接调用被代理类接口办法 * @return 被代理类办法执行返回值 * @throws Throwable */ @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("before"); MonitorUtil.start(); Object result = methodProxy.invokeSuper(object, args);// Object result = methodProxy.invoke(object, args); System.out.println("after"); MonitorUtil.finish(method.getName()); return result; }}
2. 被代理类
public class Dog { public String call() { System.out.println("wang wang wang"); return "Dog .."; } }
3. 切面办法
/** * 办法用时监控类,作为一个切面 ,具备两个办法 */public class MonitorUtil { private static final ThreadLocal<Long> tl = new ThreadLocal<>(); public static void start() { tl.set(System.currentTimeMillis()); } /** * 完结时打印耗时 * @param methodName 监控办法名 */ public static void finish(String methodName) { long finishTime = System.currentTimeMillis(); System.out.println(methodName + "办法执行耗时" + (finishTime - tl.get()) + "ms"); }}
4. 测试主类
public class TestMain { /** * 用于生成 Cglib 动静代理类工具办法 * @param target 代表须要 被代理的 委托类的 Class 对象 * @return 代理类对象 */ public static Object cglibProxyGenerator(Class target) { // 创立增强器,用来创立动静代理类 Enhancer enhancer = new Enhancer(); // 为代理类指定须要代理的类,也即是父类 enhancer.setSuperclass(target); // 设置办法拦截器回调援用,对于代理类上所有办法的调用,都会调用CallBack,而Callback则须要实现intercept() 办法进行拦挡 enhancer.setCallback(new CglibMethodInterceptor()); // 创立cglib 代理类 return enhancer.create(); } public static void main(String[] args) throws ClassNotFoundException { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "classFiles"); Dog poolDog = (Dog) cglibProxyGenerator(Dog.class); poolDog.call(); }}
(二)CGLIB生成的子类
Dog$$EnhancerByCGLIB$$beb9d601
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.allen.testDynamicProxy.cglibProxy;import java.lang.reflect.Method;import net.sf.cglib.core.ReflectUtils;import net.sf.cglib.core.Signature;import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.Factory;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;// 实现net.sf.cglib.proxy.Factory的目标是提供一些创立代理对象实例的工厂办法,这些办法会比反射创建对象快【clazz.newInstance()】public class Dog$$EnhancerByCGLIB$$beb9d601 extends Dog 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; // Dog类call的Method对象 private static final Method CGLIB$call$0$Method; // Dog类call办法的代理对象 private static final MethodProxy CGLIB$call$0$Proxy; private static final Object[] CGLIB$emptyArgs; // Object类equals办法的Method对象 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; /** * CGLIB$call$0$Method和CGLIB$call$0$Proxy就是MethodInterceptor接口的入参 * MethodProxy 比 Method反射调用办法更快 */ static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; // 加载生成的加强类 Class var0 = Class.forName("com.allen.testDynamicProxy.cglibProxy.Dog$$EnhancerByCGLIB$$beb9d601"); Class var1; // 通过反射获取Object类的Method对象 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]; // 为 Method 创立对应的 MethodProxy 对象 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"); // Dog类call办法Method对象 CGLIB$call$0$Method = ReflectUtils.findMethods(new String[]{"call", "()Ljava/lang/String;"}, (var1 = Class.forName("com.allen.testDynamicProxy.cglibProxy.Dog")).getDeclaredMethods())[0]; CGLIB$call$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "call", "CGLIB$call$0"); } final String CGLIB$call$0() { return super.call(); } // 重写 Dog类的call办法,增加CallBack回调【即执行MethodInterceptor的intercept办法,即咱们自定义的CglibMethodInterceptor的intercept办法】 public final String call() { // 这边获取MethodInterceptor为null MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { // 从新绑定MethodInterceptor CGLIB$BIND_CALLBACKS(this); // 这边还是null var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$call$0$Method, CGLIB$emptyArgs, CGLIB$call$0$Proxy) : super.call(); } 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 371634473: if (var10000.equals("call()Ljava/lang/String;")) { return CGLIB$call$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; } // 实例化构造方法会绑定CallBacks public Dog$$EnhancerByCGLIB$$beb9d601() { CGLIB$BIND_CALLBACKS(this); } // 设置CallBack到ThreadLocal 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; } /** * 判断并绑定CallBack对象【就是MethodInterceptor对象,也即自定义的CglibMethodInterceptor】 */ private static final void CGLIB$BIND_CALLBACKS(Object var0) { Dog$$EnhancerByCGLIB$$beb9d601 var1 = (Dog$$EnhancerByCGLIB$$beb9d601)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]; } } /** * 应用无参构造方法创立加强后的子类新实例 * @param callbacks 多个MethodInterceptor对象数组 * @return new instance of the same type */ public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); Dog$$EnhancerByCGLIB$$beb9d601 var10000 = new Dog$$EnhancerByCGLIB$$beb9d601(); // 将ThreadLocal的 CallBacks 至空 CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } /** * 应用无参构造方法创立加强后的子类新实例 * 该对象只能指定一个Callback【MethodInterceptor】 * @param callback 自定义的MethodInterceptor对象 * @return new instance of the same type */ public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); Dog$$EnhancerByCGLIB$$beb9d601 var10000 = new Dog$$EnhancerByCGLIB$$beb9d601(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } /** 本案例中,实例化增强子类的时候就是调用此办法 * @param types 构造方法参数类型 * @param args 构造方法参数 * @param callbacks 多个CallBack对象数组 * @return new instance of the same type */ public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); Dog$$EnhancerByCGLIB$$beb9d601 var10000 = new Dog$$EnhancerByCGLIB$$beb9d601; 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(); }}
(三)CGLIB生成的FastClass-1【简称f1】
Dog$$FastClassByCGLIB$$7ac19ed7
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.allen.testDynamicProxy.cglibProxy;import java.lang.reflect.InvocationTargetException;import net.sf.cglib.core.Signature;import net.sf.cglib.reflect.FastClass;public class Dog$$FastClassByCGLIB$$7ac19ed7 extends FastClass { public Dog$$FastClassByCGLIB$$7ac19ed7(Class var1) { super(var1); } public int getIndex(Signature var1) { String var10000 = var1.toString(); switch(var10000.hashCode()) { case 371634473: if (var10000.equals("call()Ljava/lang/String;")) { 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 3045982: if (var1.equals("call")) { 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 { Dog var10000 = (Dog)var2; int var10001 = var1; try { switch(var10001) { case 0: return var10000.call(); 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 { Dog var10000 = new Dog; Dog 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; }}
(四)CGLIB生成的FastClass-2【简称f2】
Dog$$EnhancerByCGLIB$$beb9d601$$FastClassByCGLIB$$916924fc
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.allen.testDynamicProxy.cglibProxy;import com.allen.testDynamicProxy.cglibProxy.Dog..EnhancerByCGLIB..beb9d601;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 Dog$$EnhancerByCGLIB$$beb9d601$$FastClassByCGLIB$$916924fc extends FastClass { public Dog$$EnhancerByCGLIB$$beb9d601$$FastClassByCGLIB$$916924fc(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 1; } break; case -1882565338: if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) { return 4; } break; case -1457535688: if (var10000.equals("CGLIB$STATICHOOK1()V")) { return 8; } break; case -1411842725: if (var10000.equals("CGLIB$hashCode$3()I")) { return 6; } break; case -1212270792: if (var10000.equals("CGLIB$call$0()Ljava/lang/String;")) { return 5; } break; case -894172689: if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 20; } break; case -623122092: if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) { return 13; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return 17; } break; case -419626537: if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) { return 9; } break; case 371634473: if (var10000.equals("call()Ljava/lang/String;")) { return 2; } break; case 560567118: if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) { return 12; } 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 11; } break; case 1221173700: if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 18; } break; case 1230699260: if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) { return 10; } break; case 1306468936: if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) { return 3; } break; case 1584330438: if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) { return 0; } break; case 1800494055: if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) { return 7; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return 14; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return 15; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return 16; } } return -1; } public int getIndex(String var1, Class[] var2) { switch(var1.hashCode()) { case -1776922004: if (var1.equals("toString")) { switch(var2.length) { case 0: return 15; } } break; case -1295482945: if (var1.equals("equals")) { switch(var2.length) { case 1: if (var2[0].getName().equals("java.lang.Object")) { return 14; } } } break; case -1053468136: if (var1.equals("getCallbacks")) { switch(var2.length) { case 0: return 11; } } break; case -124978609: if (var1.equals("CGLIB$equals$1")) { switch(var2.length) { case 1: if (var2[0].getName().equals("java.lang.Object")) { return 4; } } } 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 0; } } } break; case -29025555: if (var1.equals("CGLIB$hashCode$3")) { switch(var2.length) { case 0: return 6; } } break; case 3045982: if (var1.equals("call")) { switch(var2.length) { case 0: return 2; } } break; case 52714989: if (var1.equals("CGLIB$call$0")) { switch(var2.length) { case 0: return 5; } } 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 1; } } } break; case 94756189: if (var1.equals("clone")) { switch(var2.length) { case 0: return 17; } } break; case 147696667: if (var1.equals("hashCode")) { switch(var2.length) { case 0: return 16; } } break; case 161998109: if (var1.equals("CGLIB$STATICHOOK1")) { switch(var2.length) { case 0: return 8; } } break; case 495524492: if (var1.equals("setCallbacks")) { switch(var2.length) { case 1: if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) { return 9; } } } break; case 1154623345: if (var1.equals("CGLIB$findMethodProxy")) { switch(var2.length) { case 1: if (var2[0].getName().equals("net.sf.cglib.core.Signature")) { return 13; } } } break; case 1543336189: if (var1.equals("CGLIB$toString$2")) { switch(var2.length) { case 0: return 3; } } 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 20; } break; case 1730110032: if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) { return 18; } } 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 12; } } } break; case 1905679803: if (var1.equals("getCallback")) { switch(var2.length) { case 1: if (var2[0].getName().equals("int")) { return 10; } } } break; case 1951977610: if (var1.equals("CGLIB$clone$4")) { switch(var2.length) { case 0: return 7; } } } 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 { beb9d601 var10000 = (beb9d601)var2; int var10001 = var1; try { switch(var10001) { case 0: beb9d601.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 1: beb9d601.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 2: return var10000.call(); case 3: return var10000.CGLIB$toString$2(); case 4: return new Boolean(var10000.CGLIB$equals$1(var3[0])); case 5: return var10000.CGLIB$call$0(); case 6: return new Integer(var10000.CGLIB$hashCode$3()); case 7: return var10000.CGLIB$clone$4(); case 8: beb9d601.CGLIB$STATICHOOK1(); return null; case 9: var10000.setCallbacks((Callback[])var3[0]); return null; case 10: return var10000.getCallback(((Number)var3[0]).intValue()); case 11: return var10000.getCallbacks(); case 12: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 13: return beb9d601.CGLIB$findMethodProxy((Signature)var3[0]); case 14: return new Boolean(var10000.equals(var3[0])); case 15: return var10000.toString(); case 16: return new Integer(var10000.hashCode()); case 17: return var10000.clone(); case 18: return var10000.newInstance((Callback[])var3[0]); case 19: return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]); case 20: return var10000.newInstance((Callback)var3[0]); } } catch (Throwable var4) { throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); } public Object newInstance(int var1, Object[] var2) throws InvocationTargetException { beb9d601 var10000 = new beb9d601; beb9d601 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; }}
三、CGLIB代理类创立流程
代理类的创立次要是在enhancer.create()办法调用后进行的,大抵流程如下:
(一)代理类的创立
首先看下在实例化代理类期间绑定Callback
的过程「即自定义的MethodInterceptor
」,外围源码【net.sf.cglib.proxy.Enhancer.EnhancerFactoryData#newInstance】:
留神这边的setThreadCallbacks
是个final类型的变量,会在EnhancerFactoryData
的构造方法中赋值为代理类Dog$$EnhancerByCGLIB$$beb9d601
的SET_THREAD_CALLBACKS
办法对象,对应的SET_THREAD_CALLBACKS
源码如下:
// 设置CallBack到ThreadLocal public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { // CGLIB$THREAD_CALLBACKS是个final static变量,在代理类的动态代码块中赋值为ThreadLocal() // 代理类的动态代码块上面会讲到 CGLIB$THREAD_CALLBACKS.set(var0); }
最初通过反射实例化代理类Dog$$EnhancerByCGLIB$$beb9d601
的时候,会执行代理对象的静态方法块,期间会给每个被代理类Dog
的成员办法创立一个MethdProxy
代理办法对象。
(二)创立MethodProxy
MethodProxy
封装了原始Dog类的办法签名【sig1】,对应代理类办法的签名【sig2】以及代理类的一些创立信息【原始类和代理类的名称、类生成策略等等】。对应的代理类的动态代码块内容如下:
// CGLIB$call$0$Method和CGLIB$call$0$Proxy就是MethodInterceptor接口的入参static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; // 加载生成的加强类 Class var0 = Class.forName("com.allen.testDynamicProxy.cglibProxy.Dog$$EnhancerByCGLIB$$beb9d601"); Class var1; // 通过反射获取Object类的Method对象 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]; // 为 Method 创立对应的 MethodProxy 对象 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"); // Dog类call办法Method对象 CGLIB$call$0$Method = ReflectUtils.findMethods(new String[]{"call", "()Ljava/lang/String;"}, (var1 = Class.forName("com.allen.testDynamicProxy.cglibProxy.Dog")).getDeclaredMethods())[0]; // var1: 被代理类 var0:代理类 CGLIB$call$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "call", "CGLIB$call$0"); }
对应MethodProxy.create()
【net.sf.cglib.proxy.MethodProxy#creat()】办法:
/** * For internal use by {@link Enhancer} only; see the {@link net.sf.cglib.reflect.FastMethod} class * for similar functionality. * @param c1 被代理类 * @param c2 代理类 * @param desc 办法形容【"()Ljava/lang/String;"】 * @param name1 办法1名称【"call"】 * @param name2 办法2名称【"CGLIB$call$0"】 */ 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; }
对于办法签名的debug信息【前面会用这个办法签名在Fastclass中查问对应的index索引】:
(三)创立CreateInfo
CreateInfo
是MethodProxy
的一个外部类,次要保留代理类的一些创立信息。
private static class CreateInfo { // 对应Dog原始类 Class c1; // 代理类Dog$$EnhancerByCGLIB$$beb9d601 Class c2; // 代理类命名策略 NamingPolicy namingPolicy; // 代理类生成策略 GeneratorStrategy strategy; boolean attemptLoad; public CreateInfo(Class c1, Class c2) { this.c1 = c1; this.c2 = c2; AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent(); if (fromEnhancer != null) { namingPolicy = fromEnhancer.getNamingPolicy(); strategy = fromEnhancer.getStrategy(); attemptLoad = fromEnhancer.getAttemptLoad(); } } }
四、CGLIB动静代理调用流程
当执行指标办法时,代理对象调用流程如下:
置信看完下面的流程图,根本就对CGLIB的底层实现有了大抵的概念。当然上面我还会进行详细分析。
(一)重写父类办法
基于一开始的demo,笔者从调用指标办法一步步剖析。⚠️main
办法调用poolDog.call();
时,实际上执行的是代理对象的call()
办法,代理对象的生成曾经在上一节剖析过了。那咱们间接看代理对象的call()
办法,源码如下:
/** * 重写 Dog类的call办法,增加CallBack回调 * 【即执行MethodInterceptor的intercept办法,即咱们自定义的 CglibMethodInterceptor的intercept办法】 */ public final String call() { // 从成员属性CGLIB$CALLBACK_0获取MethodInterceptor // 第一次调用是null,进入上面的if逻辑 MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { // 从新绑定MethodInterceptor,并赋值给成员属性CGLIB$CALLBACK_0 CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } // @param this 代理对象自身 // @param CGLIB$call$0$Method Dog类call办法Method对象【动态代码块已赋值】 // @param CGLIB$emptyArgs Dog类call办法参数【我这边是void,所以没有】 // @param CGLIB$call$0$Proxy Dog类call办法的代理办法对象【动态代码块已赋值】 return var10000 != null ? (String)var10000.intercept(this, CGLIB$call$0$Method, CGLIB$emptyArgs, CGLIB$call$0$Proxy) : super.call(); } /** * 判断并绑定CallBack对象【就是MethodInterceptor对象,也即自定义的CglibMethodInterceptor】 */ private static final void CGLIB$BIND_CALLBACKS(Object var0) { // var0即代理类以后对象,将其对象的援用指向var1 Dog$$EnhancerByCGLIB$$beb9d601 var1 = (Dog$$EnhancerByCGLIB$$beb9d601)var0; // 这边判断是true,创立代理类的时候通过反射已将对应的Callback设置到ThreadLocal if (!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; // 将ThreadLocal中的Callback赋值给var10000 Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if (var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if (var10000 == null) { return; } } // 将Callback赋值给成员属性CGLIB$CALLBACK_0 var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; } }
当调用代理对象重写过的call()
办法时,会执行对应的办法拦截器,即咱们自定义的MethodInterceptor
中intercept
办法的逻辑【本案例中对应自定义拦截器类CglibMethodInterceptor
】,对应intercept
办法的传参和含意在下面的代码正文中已阐明。
(二)原始父类办法的匹配调用
接下来,在MethodInterceptor
的intercept
办法中调用的methodProxy.invokeSuper(object, args);
时,最终就会执行父类Dog
的call()
办法。具体怎么调用执行的,先看MethodProxy.invokeSuper(object, args);
的执行逻辑,源码如下:
/** * 调用CGLIB加强的父类指标办法 * @param obj the enhanced object, must be the object passed as the first * argument to the MethodInterceptor * @param args the arguments passed to the intercepted method; you may substitute a different * argument array as long as the types are compatible * @see MethodInterceptor#intercept * @throws Throwable the bare exceptions thrown by the called method are passed through * without wrapping in an <code>InvocationTargetException</code> */ 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(); } }
1. init()办法
在下面的流程图中咱们也大抵能看到init()办法干了些什么事。次要是在解决FastClass
,FastClass
是什么?
简略了解,FastClass
是代理对象办法 到 被代理对象办法的映射【对应FastClass的源码已在前置筹备中贴出】。
1)先看下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对象 FastClassInfo fci = new FastClassInfo(); // 生成FastClass f1,并赋值给FastClassInfo的成员属性 fci.f1 = helper(ci, ci.c1); fci.f2 = helper(ci, ci.c2); // 依据办法签名,获取代理类中对应call办法在f1中的索引 fci.i1 = fci.f1.getIndex(sig1); // 依据办法签名,获取代理类中对应call办法在f2中的索引 fci.i2 = fci.f2.getIndex(sig2); fastClassInfo = fci; createInfo = null; } } } }/* * FastClassInfo也是MethodProxy的一个外部类 */private static class FastClassInfo { // 对应前置筹备中的f1 FastClass f1; // 对应前置筹备中的f2 FastClass f2; int i1; int i2; }
init()
办法其实就是创立了两个FastClass
,而后建设FastClass 到 代理对象 对于 指标办法 的 索引。
2)fci.f2.invoke(fci.i2, obj, args);
invoke的传参阐明:
- i2: 获取代理类中对应call办法在f2中的索引
- obj: 代理对象自身
- args: 指标办法的传参
f2中invoke局部源码:
接下就会调用代理对象对应的办法:
看到这是不是有点明了了,最初这不就是执行了咱们父类Dog
的call()
办法吗。那整个外围的实现逻辑和调用流程大抵就是这样的。
(三)CGLIB死循环了
下面一大节对于指标办法的调用是通过net.sf.cglib.proxy.MethodProxy#invokeSuper
实现的,CGLIB中还有一个net.sf.cglib.proxy.MethodProxy#invoke
。在自定义的MethodProxy中,将invokeSuper改成invoke,运行一下,报错了,有限递归导致栈溢出。
在解释起因之前,有没有发现一个问题,后面不是生成了两个FastClass吗,截止当初咱们只用到了一个。你的猜测正确,invoke
办法就是用的f1中的索引。
死循话的问题我这边不具体解释,以一张图阐明【其中的元素信息齐全基于前置筹备的代码,同学们能够本人本地写个demo尝试】:
五、性能:CGLIB vs JDK
其实说实话,工作中并没有说单单就因为将动静代理模式从JDK换成CGLIB,性能就有显著晋升的状况,大部分状况性能相差不多。然而显著CGLIB适用性更广,SpringBoot将AOP的动静代理默认设置成了CGLIB,我想预计也不是性能使然。
实践上说,针对JDK动静代理的Method.invoke()
和CGLIB的MethodProxy.invokeSuper()
这两个invoke来说,CGLIB感觉更加优雅些,然而刚开始第一次调用CGLIB是比较慢的,还记得下面提到的init()
吗。非要钻牛角尖说CGLIB性能更好的话,可能是MethodAccessor
的锅。
Method.invoke(target,params)
,理论是MethodAccessor
实例真正实现反射调用。Java 版本的MethodAccessorImpl
调用效率比Native
版本要快 20 倍以上,然而 Java 版本加载时要比 Native 多耗费 3-4 倍资源,所以默认会调用 Native 版本,如果调用次数超过 15 次当前,就会抉择运行效率更高的 Java 版本。然而⚠️:寄存method的reflectionData
是SoftReference
的,即在某些内存比拟刻薄的状况下是可能被回收的【通过-XX:SoftRefLRUPolicyMSPerMB
这个参数来管制回收的机会】。一旦回收,就须要调用getDeclaredMethods0
进行遍历查找,从新缓存。
对于JDK代理的细节,能够参考我之前的文章:https://www.heapdump.cn/artic...
over,心愿这篇吐血肝货,能够帮你了解CGLIB底层实现原理。持续肝·····