CGLIB动态代理底层实现原理

一、前言 最近在探究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 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生成的子类
【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.(); 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.(); 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.(); 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()方法调用后进行的,大致流程如下:
CGLIB动态代理底层实现原理
文章图片

(一)代理类的创建
? 首先看下在实例化代理类期间绑定Callback的过程「即自定义的MethodInterceptor」,核心源码【net.sf.cglib.proxy.Enhancer.EnhancerFactoryData#newInstance】:
CGLIB动态代理底层实现原理
文章图片

注意这边的setThreadCallbacks是个final类型的变量,会在EnhancerFactoryData的构造方法中赋值为代理类Dog$$EnhancerByCGLIB$$beb9d601SET_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索引】:
CGLIB动态代理底层实现原理
文章图片

(三)创建CreateInfo
? CreateInfoMethodProxy的一个内部类,主要保存代理类的一些创建信息。
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动态代理底层实现原理
文章图片

相信看完上面的流程图,基本就对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()方法时,会执行对应的方法拦截器,即我们自定义的MethodInterceptorintercept方法的逻辑【本案例中对应自定义拦截器类CglibMethodInterceptor】,对应intercept方法的传参和含义在上面的代码注释中已说明。
(二)原始父类方法的匹配调用
? 接下来,在MethodInterceptorintercept方法中调用的methodProxy.invokeSuper(object, args); 时,最终就会执行父类Dogcall()方法。具体怎么调用执行的,先看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 InvocationTargetException */ 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()方法干了些什么事。主要是在处理FastClassFastClass是什么?
简单理解,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部分源码:
CGLIB动态代理底层实现原理
文章图片

接下就会调用代理对象对应的方法:
CGLIB动态代理底层实现原理
文章图片

看到这是不是有点明了了,最后这不就是执行了我们父类Dogcall()方法吗。那整个核心的实现逻辑和调用流程大致就是这样的。
(三)CGLIB死循环了
? 上面一小节关于目标方法的调用是通过net.sf.cglib.proxy.MethodProxy#invokeSuper完成的,CGLIB中还有一个net.sf.cglib.proxy.MethodProxy#invoke。在自定义的MethodProxy中,将invokeSuper改成invoke,运行一下,报错了,无限递归导致栈溢出。
? 在解释原因之前,有没有发现一个问题,前面不是生成了两个FastClass吗,截止现在我们只用到了一个。你的猜想正确,invoke方法就是用的f1中的索引。
? 死循话的问题我这边不详细解释,以一张图说明【其中的元素信息完全基于前置准备的代码,同学们可以自己本地写个demo尝试】:
CGLIB动态代理底层实现原理
文章图片

五、性能: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的reflectionDataSoftReference的,即在某些内存比较苛刻的情况下是可能被回收的【通过-XX:SoftRefLRUPolicyMSPerMB这个参数来控制回收的时机】。一旦回收,就需要调用getDeclaredMethods0 进行遍历查找,重新缓存。
关于JDK代理的细节,可以参考我之前的文章:https://www.heapdump.cn/artic...
? over,希望这篇吐血肝货,可以帮你理解CGLIB底层实现原理。继续肝·····

    推荐阅读