cglib动态代理

article/2025/10/31 16:05:09

前面介绍了代理模式和JAVA动态代理,这片文章主要解析cglib动态代理实现。

基本介绍

CGLIB(Code Generation Library),是一个强大的,高性能,高质量的 Code 生成类库,它可以在运行期扩展 Java 类与实现 Java 接口。

pom

        <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.7</version></dependency>

cglib案例

目标类

public interface UserService {public void say();public void say2();}public class UserServiceImpl implements UserService{@Overridepublic void say() {System.out.println("hello");say2();}@Overridepublic void say2() {System.out.println("hello2");}public final void finalMethod() {System.out.println("final method");}public static void staticMethod() {System.out.println("static method");}
}

方法拦截器

MethodInterceptor类似于jdk动态代理的InvocationHandler,方法调用前后进行增强。
public class MyInterceptor implements MethodInterceptor {private Object target;public MyInterceptor(Object target) {this.target = target;}/**** @param o 代理对象* @param method 被代理对象的方法* @param objects 方法入参* @param methodProxy 代理方法* @return* @throws Throwable*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib before");// 调用代理类FastClass对象Object result =  methodProxy.invokeSuper(o, objects);
//        Object result = methodProxy.invoke(target, objects);System.out.println("cglib after");return result;}}

客户端

public class CglibClient {public static void main(String[] args) {UserServiceImpl target = new UserServiceImpl();// 代理类class文件存入本地磁盘方便我们反编译查看源码System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code");// 通过CGLIB动态代理获取代理对象的过程Enhancer enhancer = new Enhancer();// 设置enhancer对象的父类enhancer.setSuperclass(UserServiceImpl.class);// 设置enhancer的回调对象enhancer.setCallback(new MyInterceptor(target));// 创建代理对象UserServiceImpl userService = (UserServiceImpl)enhancer.create();// 通过代理对象调用目标方法userService.say();userService.finalMethod();UserServiceImpl.staticMethod();}}

输出结果

cglib before
hello
cglib before
hello2
cglib after
cglib after
final method
static method

打印结果显示,final,static等方法不会代码增强,say()方法内部调用say2(),say2()方法也会进行增强。具体原因后面代理类字节码反编译解释。

字节码解析

// 代理类class文件存入本地磁盘方便我们反编译查看源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code");

设置如上系统参数,会在code目录打印cglib动态生成的代码

UserServiceImpl$$EnhancerByCGLIB$$30794112:cglib生成的代理类,继承被代理类UserServiceImpl,实现net.sf.cglib.proxy.Factory接口
UserServiceImpl$$EnhancerByCGLIB$$30794112$$FastClassByCGLIB$$5d581559:代理类UserServiceImpl$$EnhancerByCGLIB$$30794112的索引类,继承net.sf.cglib.reflect.FastClass,记录了代理类的所有方法的索引,通过索引调用代理类的对应方法。
UserServiceImpl$$FastClassByCGLIB$$667bfe0a:是被代理类proxy.UserServiceImpl的索引类。功能同上

代理类

代理类重写了被代理类的say,say2方法,还有Object的equals,toString,hashCode,clone方法,say方法内部调用proxy.cglib.MyInterceptor#intercept进行增强。

public class UserServiceImpl$$EnhancerByCGLIB$$30794112 extends UserServiceImpl 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$say2$0$Method;private static final MethodProxy CGLIB$say2$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$say$1$Method;private static final MethodProxy CGLIB$say$1$Proxy;private static final Method CGLIB$equals$2$Method;private static final MethodProxy CGLIB$equals$2$Proxy;private static final Method CGLIB$toString$3$Method;private static final MethodProxy CGLIB$toString$3$Proxy;private static final Method CGLIB$hashCode$4$Method;private static final MethodProxy CGLIB$hashCode$4$Proxy;private static final Method CGLIB$clone$5$Method;private static final MethodProxy CGLIB$clone$5$Proxy;static void CGLIB$STATICHOOK1() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class var0 = Class.forName("proxy.UserServiceImpl$$EnhancerByCGLIB$$30794112");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$2$Method = var10000[0];CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");CGLIB$toString$3$Method = var10000[1];CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");CGLIB$hashCode$4$Method = var10000[2];CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");CGLIB$clone$5$Method = var10000[3];CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");var10000 = ReflectUtils.findMethods(new String[]{"say2", "()V", "say", "()V"}, (var1 = Class.forName("proxy.UserServiceImpl")).getDeclaredMethods());CGLIB$say2$0$Method = var10000[0];CGLIB$say2$0$Proxy = MethodProxy.create(var1, var0, "()V", "say2", "CGLIB$say2$0");CGLIB$say$1$Method = var10000[1];CGLIB$say$1$Proxy = MethodProxy.create(var1, var0, "()V", "say", "CGLIB$say$1");}final void CGLIB$say2$0() {super.say2();}public final void say2() {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$say2$0$Method, CGLIB$emptyArgs, CGLIB$say2$0$Proxy);} else {super.say2();}}final void CGLIB$say$1() {super.say();}public final void say() {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$say$1$Method, CGLIB$emptyArgs, CGLIB$say$1$Proxy);} else {super.say();}}final boolean CGLIB$equals$2(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$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);return var2 == null ? false : (Boolean)var2;} else {return super.equals(var1);}}final String CGLIB$toString$3() {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$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();}final int CGLIB$hashCode$4() {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$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);return var1 == null ? 0 : ((Number)var1).intValue();} else {return super.hashCode();}}final Object CGLIB$clone$5() 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$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();}public static MethodProxy CGLIB$findMethodProxy(Signature var0) {String var10000 = var0.toString();switch(var10000.hashCode()) {case -909388886:if (var10000.equals("say()V")) {return CGLIB$say$1$Proxy;}break;case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return CGLIB$clone$5$Proxy;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return CGLIB$equals$2$Proxy;}break;case 1874011246:if (var10000.equals("say2()V")) {return CGLIB$say2$0$Proxy;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return CGLIB$toString$3$Proxy;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return CGLIB$hashCode$4$Proxy;}}return null;}public UserServiceImpl$$EnhancerByCGLIB$$30794112() {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) {UserServiceImpl$$EnhancerByCGLIB$$30794112 var1 = (UserServiceImpl$$EnhancerByCGLIB$$30794112)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);UserServiceImpl$$EnhancerByCGLIB$$30794112 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$30794112();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Callback var1) {CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});UserServiceImpl$$EnhancerByCGLIB$$30794112 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$30794112();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {CGLIB$SET_THREAD_CALLBACKS(var3);UserServiceImpl$$EnhancerByCGLIB$$30794112 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$30794112;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)

记录了代理类UserServiceImpl$EnhancerByCGLIB$30794112的所有方法的索引,通过proxy.UserServiceImpl$EnhancerByCGLIB$30794112$FastClassByCGLIB$5d581559#getIndex(net.sf.cglib.core.Signature)获取索引,通过proxy.UserServiceImpl$EnhancerByCGLIB$30794112$FastClassByCGLIB$5d581559#invoke方法,根据索引调用对应的代理类的方法。

public class UserServiceImpl$$EnhancerByCGLIB$$30794112$$FastClassByCGLIB$$5d581559 extends FastClass {public UserServiceImpl$$EnhancerByCGLIB$$30794112$$FastClassByCGLIB$$5d581559(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 5;}break;case -1457535688:if (var10000.equals("CGLIB$STATICHOOK1()V")) {return 8;}break;case -1411812934:if (var10000.equals("CGLIB$hashCode$4()I")) {return 13;}break;case -909388886:if (var10000.equals("say()V")) {return 1;}break;case -894172689:if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 22;}break;case -623122092:if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {return 15;}break;case -560613858:if (var10000.equals("finalMethod()V")) {return 23;}break;case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return 19;}break;case -419626537:if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {return 3;}break;case 374345669:if (var10000.equals("CGLIB$equals$2(Ljava/lang/Object;)Z")) {return 11;}break;case 560567118:if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {return 2;}break;case 811063227:if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 21;}break;case 906868927:if (var10000.equals("CGLIB$say2$0()V")) {return 9;}break;case 973717575:if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {return 7;}break;case 1221173700:if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 20;}break;case 1230699260:if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {return 6;}break;case 1517819849:if (var10000.equals("CGLIB$toString$3()Ljava/lang/String;")) {return 12;}break;case 1540724864:if (var10000.equals("CGLIB$say$1()V")) {return 10;}break;case 1584330438:if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {return 4;}break;case 1625931814:if (var10000.equals("staticMethod()V")) {return 24;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 16;}break;case 1874011246:if (var10000.equals("say2()V")) {return 0;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 17;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 18;}break;case 2011844968:if (var10000.equals("CGLIB$clone$5()Ljava/lang/Object;")) {return 14;}}return -1;}public int getIndex(String var1, Class[] var2) {switch(var1.hashCode()) {case -1776922004:if (var1.equals("toString")) {switch(var2.length) {case 0:return 17;}}break;case -1295482945:if (var1.equals("equals")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 16;}}}break;case -1053468136:if (var1.equals("getCallbacks")) {switch(var2.length) {case 0:return 7;}}break;case -124978608:if (var1.equals("CGLIB$equals$2")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 11;}}}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 4;}}}break;case -29025554:if (var1.equals("CGLIB$hashCode$4")) {switch(var2.length) {case 0:return 13;}}break;case 113643:if (var1.equals("say")) {switch(var2.length) {case 0:return 1;}}break;case 3522983:if (var1.equals("say2")) {switch(var2.length) {case 0:return 0;}}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 5;}}}break;case 94756189:if (var1.equals("clone")) {switch(var2.length) {case 0:return 19;}}break;case 147696667:if (var1.equals("hashCode")) {switch(var2.length) {case 0:return 18;}}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 3;}}}break;case 511112950:if (var1.equals("CGLIB$say2$0")) {switch(var2.length) {case 0:return 9;}}break;case 1124865749:if (var1.equals("CGLIB$say$1")) {switch(var2.length) {case 0:return 10;}}break;case 1154623345:if (var1.equals("CGLIB$findMethodProxy")) {switch(var2.length) {case 1:if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {return 15;}}}break;case 1154711791:if (var1.equals("staticMethod")) {switch(var2.length) {case 0:return 24;}}break;case 1543336190:if (var1.equals("CGLIB$toString$3")) {switch(var2.length) {case 0:return 12;}}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 22;}break;case 1730110032:if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {return 20;}}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 21;}}}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 2;}}}break;case 1900285431:if (var1.equals("finalMethod")) {switch(var2.length) {case 0:return 23;}}break;case 1905679803:if (var1.equals("getCallback")) {switch(var2.length) {case 1:if (var2[0].getName().equals("int")) {return 6;}}}break;case 1951977611:if (var1.equals("CGLIB$clone$5")) {switch(var2.length) {case 0:return 14;}}}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 {30794112 var10000 = (30794112)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.say2();return null;case 1:var10000.say();return null;case 2:var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);return null;case 3:var10000.setCallbacks((Callback[])var3[0]);return null;case 4:30794112.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);return null;case 5:30794112.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);return null;case 6:return var10000.getCallback(((Number)var3[0]).intValue());case 7:return var10000.getCallbacks();case 8:30794112.CGLIB$STATICHOOK1();return null;case 9:var10000.CGLIB$say2$0();return null;case 10:var10000.CGLIB$say$1();return null;case 11:return new Boolean(var10000.CGLIB$equals$2(var3[0]));case 12:return var10000.CGLIB$toString$3();case 13:return new Integer(var10000.CGLIB$hashCode$4());case 14:return var10000.CGLIB$clone$5();case 15:return 30794112.CGLIB$findMethodProxy((Signature)var3[0]);case 16:return new Boolean(var10000.equals(var3[0]));case 17:return var10000.toString();case 18:return new Integer(var10000.hashCode());case 19:return var10000.clone();case 20:return var10000.newInstance((Callback[])var3[0]);case 21:return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);case 22:return var10000.newInstance((Callback)var3[0]);case 23:var10000.finalMethod();return null;case 24:UserServiceImpl.staticMethod();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 {30794112 var10000 = new 30794112;30794112 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 24;}
}

被代理类索引类(继承FastClass)

原理同上

public class UserServiceImpl$$FastClassByCGLIB$$667bfe0a extends FastClass {public UserServiceImpl$$FastClassByCGLIB$$667bfe0a(Class var1) {super(var1);}public int getIndex(Signature var1) {String var10000 = var1.toString();switch(var10000.hashCode()) {case -909388886:if (var10000.equals("say()V")) {return 1;}break;case -560613858:if (var10000.equals("finalMethod()V")) {return 2;}break;case 1625931814:if (var10000.equals("staticMethod()V")) {return 3;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 4;}break;case 1874011246:if (var10000.equals("say2()V")) {return 0;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 5;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 6;}}return -1;}public int getIndex(String var1, Class[] var2) {switch(var1.hashCode()) {case -1776922004:if (var1.equals("toString")) {switch(var2.length) {case 0:return 5;}}break;case -1295482945:if (var1.equals("equals")) {switch(var2.length) {case 1:if (var2[0].getName().equals("java.lang.Object")) {return 4;}}}break;case 113643:if (var1.equals("say")) {switch(var2.length) {case 0:return 1;}}break;case 3522983:if (var1.equals("say2")) {switch(var2.length) {case 0:return 0;}}break;case 147696667:if (var1.equals("hashCode")) {switch(var2.length) {case 0:return 6;}}break;case 1154711791:if (var1.equals("staticMethod")) {switch(var2.length) {case 0:return 3;}}break;case 1900285431:if (var1.equals("finalMethod")) {switch(var2.length) {case 0:return 2;}}}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 {UserServiceImpl var10000 = (UserServiceImpl)var2;int var10001 = var1;try {switch(var10001) {case 0:var10000.say2();return null;case 1:var10000.say();return null;case 2:var10000.finalMethod();return null;case 3:UserServiceImpl.staticMethod();return null;case 4:return new Boolean(var10000.equals(var3[0]));case 5:return var10000.toString();case 6: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 {UserServiceImpl var10000 = new UserServiceImpl;UserServiceImpl 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 6;}
}

代码跟踪

通过调用栈显示,

proxy.UserServiceImpl$EnhancerByCGLIB$30794112#say 内部调用了proxy.cglib.MyInterceptor#intercept ,intercept内部调用了net.sf.cglib.proxy.MethodProxy#invokeSuper,invokeSuper内部调用了proxy.UserServiceImpl$EnhancerByCGLIB$30794112$FastClassByCGLIB$5d581559#invoke,参数索引值是10。如下图二,索引10是代理类proxy.UserServiceImpl$EnhancerByCGLIB$30794112#CGLIB$say$0方法,CGLIB$say$0方法内部调用了super.say()父类(被代理类)方法。

Java动态代理和cglib比较

生成代理类技术不同

  • java动态代理:jdk自带类ProxyGenerator生成class字节码
  • cglib:通过ASM框架生成class字节码文件

生成代理类的方式不同

  • java动态代理:代理类继承java.lang.reflect.Proxy,实现被代理类的接口
  • cglib:代理类继承被代理类,实现net.sf.cglib.proxy.Factory

生成类数量不同

  • java动态代理:生成一个proxy类
  • cglib:生成一个proxy,两个fastclass类

调用方式不同

  • java动态代理:代理类->InvocationHandler->反射调用被代理类方法
  • cglib:代理类->MethodInterceptor->调用索引类invoke->直接调用被代理类方法

性能比较

网上找到比较多的说明如下:

jdk6之前比使用 Java反射效率要高,在 jdk6jdk7jdk8 逐步对 JDK 动态代理优化之后,在调用次数较少的情况下,JDK 代理效率 高于 CGLIB 代理效率。只有当进行大量调用的时候,jdk6jdk7CGLIB 代理效率低一点,但是到 jdk8 的时候,jdk 代理效率高于 CGLIB 代理,总之,每一次 jdk 版本升级JDK 代理效率 都得到提升,而 CGLIB 代理效率 确有点跟不上步伐。


http://chatgpt.dhexx.cn/article/dNSMGhaL.shtml

相关文章

动态代理之 cglib 实现

&#xff08;尊重劳动成果&#xff0c;转载请注明出处&#xff1a;https://blog.csdn.net/qq_25827845/article/details/87513102冷血之心的博客&#xff09; 目录 前言&#xff1a; 正文&#xff1a; AOP&#xff08;面向切面编程&#xff09; JDK动态代理 cglib实现动态…

CGLIB介绍与原理

一、什么是 CGLIB? CGLIB是一个功能强大&#xff0c;高性能的代码生成包。它为没有实现接口的类提供代理&#xff0c;为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理&#xff0c;但当要代理的类没有实现接口或者为了更好的性能&#xff0c;CGLIB是一个…

CGLIB(Code Generation Library)详解

什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c;同样使用CGLIB来代理单端&#xff08;多对一和一对一&#xff09;…

【动态代理】CGLIB 动态代理的使用及原理

1. CGLIB 动态代理介绍 什么是 CGLIB&#xff1f; CGLIB是一个功能强大&#xff0c;高性能的代码生成包。它为没有实现接口的类提供代理&#xff0c;为JDK的动态代理提供了很好的补充。 通常可以使用Java的动态代理创建代理&#xff0c;但当要代理的类没有实现接口或者为了更…

CGLIB详解(最详细)

转载地址:https://blog.csdn.net/danchu/article/details/70238002 什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c…

GPG error解决方案

问题: sudo apt-get update时报错GPG error 解决方案: // F42ED6FBAB17C654是根据你报错那一行确定的 sudo gpg --keyserver keyserver.ubuntu.com --recv F42ED6FBAB17C654 sudo gpg --export --armor F42ED6FBAB17C654 | sudo apt-key add -然后: sudo apt-get update

GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

阿里云CentOS 7.9 64位 搭建网站踩坑实录 问题1.GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql Failing package is: mysql-community-libs-compat-5.7.37-1.el7.x86_64 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql …

gpg文件加密解密

使用Ubuntu对文件进行gpg格式的加密和解密 安装 下载源码安装  ./configure   make   make install 命令安装 Debian环境 sudo apt-get install gnupg Fedora 环境 yum install gnupg 加密 gpg -c abc.txt 会让输入一个加密的密码&#xff0c;需要自己输入 解密 gpg -o …

GPG(GnuPG)的安装和使用

基于网络的开源项目&#xff0c;能给用户带来在公共标准基础上的自由发挥&#xff0c;并且能很好地给每个自愿人士提供了共享贡献的机会。但是&#xff0c;同时也因为大众化给使用共享的程序员或团队带来了安全性问题。 当程序员从中央仓库下载第三方构件的时候&#xff0c;下载…

gpg使用

https://blog.csdn.net/weixin_42559321/article/details/82147888 https://www.cnblogs.com/wanghongli/archive/2018/01/08/8241809.html rpm2cpio *.rpm | cpio -imd       #解压一个rpm包rpm -ivh *.rpm --force       #强制安装这个rpm包rpm -iv…

如何在Git中使用GPG

开篇之前&#xff0c;先给大伙看点东西 是不是很想要&#xff1f;你找对地方了! 下面是教程&#xff1a; 在 “开始”菜单 打开Git Bash 输入 gpg --gen-key 显示如下 $ gpg --gen-keygpg (GnuPG) 2.2.13-unknown; Copyright (C) 2019 Free Software Foundation, Inc.This …

成功解决gpg: 找不到有效的 OpenPGP 数据

在Ubuntu系统上安装docker时出现gpg: 找不到有效的 OpenPGP 数据的报错 解决方案&#xff1a; wget https://download.docker.com/linux/ubuntu/gpg sudo apt-key add gpg随后再次执行下载指令&#xff0c;解决报错 成功解决gpg: 找不到有效的 OpenPGP 数据的报错 欢迎小伙…

GPG Overview

Overview PGP目前支持的算法 非对称算法: RSA, ELG, DSA, ECDH, ECDSA, EDDSA对称算法: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256哈希算法: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224压缩算法: Uncompres…

GPG 使用初步

GPG 使用初步 1. PGP 软件的安装 PGP 的版本有很多&#xff0c;但由于其商业软件的特性&#xff0c;不能自由使用&#xff0c;自由软件基金会决定开发一个 PGP 的替代品&#xff0c;取名为 GnuPG &#xff0c;这就是 PGP 的由来   GPG 是基于命令行的程序&#xff0c;主要面…

gpg加解密软件学习

为什么要学习gpg呢&#xff1f;因为要在Linux下把一个邮箱的密码加密&#xff0c;不让其他人看到该邮箱真正的密码。 为了不让其他人看到真正的邮箱密码&#xff0c;我们需要对其进行加密。 加密的方式是先把密码先写到一个文件A中&#xff0c;然后使用相关的加密软件对该文件…

java动态代理

java动态代理实现与原理详细分析 原文地址 关于Java中的动态代理&#xff0c;我们首先需要了解的是一种常用的设计模式--代理模式&#xff0c;而对于代理&#xff0c;根据创建代理类的时间点&#xff0c;又可以分为静态代理和动态代理。 一、代理模式 代理模式是常用的java…

动态规划 --- 算法思想介绍

一.动态规划的基本概念 动态规划在五种算法设计方法中难度最大&#xff0c;它建立在最优原则的基础上.采用动态规划方法&#xff0c;可以高效地解决许多用贪婪算法或分治法无法解决的问题.动态规划(dynamic programming)属运筹学中的规划论分支&#xff0c;是求解决策过程最优…

动态规划算法详解

动态规划算法通常用于求解具有最优性质的问题 基本概念 动态规划过程是&#xff1a;每次决策依赖于当前状态&#xff0c;又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的&#xff0c;所以&#xff0c;这种多阶段最优化决策解决问题的过程就称为动态规划(DP)。…

动态规划原理

1. 基本概念 动态规划通过拆分问题&#xff0c;将问题拆分成许多的子问题&#xff0c;定义问题状态和状态之间的关系&#xff08;即状态转移方程或递推公式&#xff09;&#xff0c;使得问题能够以递推&#xff08;或者说分治&#xff09;的方式去解决。按顺序求解子问题&…

动态代理详解

想要更加透彻的理解动态代理&#xff0c;首先要熟悉下静态代理 一、静态代理 总结来说&#xff1a;目标类和代理类实现了相同的接口&#xff0c;在代理类中依赖了目标类&#xff0c;代理类的方法中调用了目标类的方法&#xff0c;并做了一些增强性的工作。 1、实现静态代理&…