当前位置: 首页 > news >正文

java动态代理

静态代理和动态代理

  • 1、代理模式
  • 2、静态代理
    • 2.1 定义接口
    • 2.2 被代理对象实现
    • 2.3 代理对象
    • 2.4 客户端
  • 3、JDK动态代理
    • 3.1 JDK动态代理例子
      • 3.1.1 定义接口
      • 3.1.2 被代理对象实现
      • 3.1.3 实现InvocationHandler接口
      • 3.1.4 创建代理对象
    • 3.2 动态代理底层原理
    • 3.3 查看生成的代理类
  • 4、CGLIB
    • 4.1 CGLIB的例子
      • 4.1.1 定义目标对象
      • 4.1.2 自定义方法拦截器
      • 4.1.3 使用动态代理
    • 4.2 CGLIB原理
  • 5、Spring切面
    • 5.1 定义注解
    • 5.2 定义被代理对象
    • 5.3 打印CGLIB实现的子类
    • 5.4 查询CGLIB生成的子类

如有侵权,请联系~
如有错误,也请欢迎批评指正~

1、代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。代理对象代替真实对象,并在访问之前或之后执行一些额外的操作。这种模式有助于实现延迟加载、安全控制、日志记录等功能。
代理的UML图:

在这里插入图片描述
在这里插入图片描述
代理主要分为两种:静态代理和动态代理。这两种代理的区分:这种代理关系是在编译期间确定【静态代理】的还是运行期间确定的【动态代理】。

2、静态代理

静态代理可以理解为程序员自己手动写代理类或者通过工具自动生成代理类,即在运行之前代理类的class文件已经真实存在类。
基于上述的UML图,实现一个静态代理:

2.1 定义接口

public interface Shop {void sell();
}

2.2 被代理对象实现

public class ZhangLiangMaLaTang implements Shop {@Overridepublic void sell() {System.out.println("张亮麻辣烫");}
}

2.3 代理对象

public class Meituan implements Shop {private Shop shop = new ZhangLiangMaLaTang();@Overridepublic void sell() {System.out.println("美团欢迎您");shop.sell();  // 调用目标对象【张亮麻辣烫】System.out.println("召唤骑手");}
}

2.4 客户端

用户想要点麻辣烫,需要通过美团点餐:

public class Client {public static void main(String[] args) {Shop meituan = new Meituan();meituan.sell(); // 通过代理调用真实对象的方法}
}

3、JDK动态代理

动态代理和静态代理不同的是,动态代理是在程序运行之前并没有class字节码文件,而是在运行过程中动态生成的。动态代理的实现:JDK动态代理、CGLIB、Javassist、ASM等。

3.1 JDK动态代理例子

使用JDK动态代理,需要被代理的对象实现接口。先看下使用JDK动态代理如何实现上述的例子:

3.1.1 定义接口

public interface Shop {void sell();
}

3.1.2 被代理对象实现

public class ZhangLiangMaLaTang implements Shop {@Overridepublic void sell() {System.out.println("张亮麻辣烫");}
}

3.1.3 实现InvocationHandler接口

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class MeituanProxyHandler implements InvocationHandler {private final Shop shop;public MeituanProxyHandler(Shop shop) {this.shop = shop;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("美团欢迎您");Object result = method.invoke(shop, args); // 调用真实对象的方法System.out.println("召唤骑手");return result;}public Shop createProxy(){Shop proxyInstance = (Shop) Proxy.newProxyInstance(Shop.class.getClassLoader(),  // ClassLoadernew Class[]{Shop.class},      // 接口this                               // InvocationHandler);}
}

3.1.4 创建代理对象

import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {Shop zhangLiangMaLaTang = new ZhangLiangMaLaTang();MeituanProxyHandler handler = new MeituanProxyHandler(zhangLiangMaLaTang);Shop meituan = handler.createProxy();// 使用代理实例meituan.sell();}
}

3.2 动态代理底层原理

接下来看下,动态代理如何实现的,并且又是如何调用到了InvocationHandler接口上呢。首先JDK动态代理最重要的一个类就是Proxy:

public class Proxy implements java.io.Serializable {// 这个代理对象的InvocationHandlerprotected InvocationHandler h;// 用来缓存代理类private static final WeakCache<ClassLoader, Class<?>[], Class<?>>proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());// 不允许外部实例化private Proxy() {}protected Proxy(InvocationHandler h) {Objects.requireNonNull(h);this.h = h;}// 创建目标对象的代理对象【这个代理对象会将流量分发到特定的invocationHandler(h)上】public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{Objects.requireNonNull(h);final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}// 查找或者创建目标对象的代理类Class<?> cl = getProxyClass0(loader, intfs);// 利用反射获取带有invocationHandler的构造方法,并进行创建try {if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}return cons.newInstance(new Object[]{h});} catch (IllegalAccessException|InstantiationException e) {throw new InternalError(e.toString(), e);} catch (InvocationTargetException e) {Throwable t = e.getCause();if (t instanceof RuntimeException) {throw (RuntimeException) t;} else {throw new InternalError(t.toString(), t);}} catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}}// 获取目标对象的代理类private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// 如果实现给定接口【目标对象的接口】的给定加载器【目标对象的类加载器】定义的代理类存在,则将简单地返回缓存的副本;否则,它将通过 ProxyClassFactory 创建代理类return proxyClassCache.get(loader, interfaces);}
}

ProxyClassFactory专门用来生成和定义代理对象的工厂:

private static final class ProxyClassFactoryimplements BiFunction<ClassLoader, Class<?>[], Class<?>>
{// 所有代理类名字的前缀private static final String proxyClassNamePrefix = "$Proxy";// 每个代理类名字的后缀,和proxyClassNamePrefix一起构成代理类的名字private static final AtomicLong nextUniqueNumber = new AtomicLong();// 生成的代理对象由该类加载器loader加载并实现interfaces所有接口@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);// 一系列的校验for (Class<?> intf : interfaces) {/** Verify that the class loader resolves the name of this* interface to the same Class object.*/Class<?> interfaceClass = null;try {interfaceClass = Class.forName(intf.getName(), false, loader);} catch (ClassNotFoundException e) {}if (interfaceClass != intf) {throw new IllegalArgumentException(intf + " is not visible from class loader");}/** Verify that the Class object actually represents an* interface.*/if (!interfaceClass.isInterface()) {throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");}/** Verify that this interface is not a duplicate.*/if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());}}// 获取代理类的包名String proxyPkg = null;     // package to define proxy class inint accessFlags = Modifier.PUBLIC | Modifier.FINAL;/** Record the package of a non-public proxy interface so that the* proxy class will be defined in the same package.  Verify that* all non-public proxy interfaces are in the same package.*/for (Class<?> intf : interfaces) {int flags = intf.getModifiers();if (!Modifier.isPublic(flags)) {accessFlags = Modifier.FINAL;String name = intf.getName();int n = name.lastIndexOf('.');String pkg = ((n == -1) ? "" : name.substring(0, n + 1));if (proxyPkg == null) {proxyPkg = pkg;} else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException("non-public interfaces from different packages");}}}if (proxyPkg == null) {// if no non-public proxy interfaces, use com.sun.proxy packageproxyPkg = ReflectUtil.PROXY_PACKAGE + ".";}/** Choose a name for the proxy class to generate.*/long num = nextUniqueNumber.getAndIncrement();// 代理类的全类名String proxyName = proxyPkg + proxyClassNamePrefix + num;/** Generate the specified proxy class.*/// 生成代理类【字节码数据】byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);try {// 字节码转换为Class对象return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);} catch (ClassFormatError e) {/** A ClassFormatError here means that (barring bugs in the* proxy class generation code) there was some other* invalid aspect of the arguments supplied to the proxy* class creation (such as virtual machine limitations* exceeded).*/throw new IllegalArgumentException(e.toString());}}
}

ProxyGenerator生成代理类:

public class ProxyGenerator {public static byte[] generateProxyClass(final String name,Class<?>[] interfaces) {return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));}public static byte[] generateProxyClass(final String name,Class<?>[] interfaces,int accessFlags){// 生成代理类ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);final byte[] classFile = gen.generateClassFile();// 是否将生成的代理类保存到文件中if (saveGeneratedFiles) {java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {public Void run() {try {int i = name.lastIndexOf('.');Path path;if (i > 0) {Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));Files.createDirectories(dir);path = dir.resolve(name.substring(i+1, name.length()) + ".class");} else {path = Paths.get(name + ".class");}Files.write(path, classFile);return null;} catch (IOException e) {throw new InternalError("I/O exception saving generated file: " + e);}}});}return classFile;}private byte[] generateClassFile() {/* ============================================================* Step 1: Assemble ProxyMethod objects for all methods to* generate proxy dispatching code for.*//** Record that proxy methods are needed for the hashCode, equals,* and toString methods of java.lang.Object.  This is done before* the methods from the proxy interfaces so that the methods from* java.lang.Object take precedence over duplicate methods in the* proxy interfaces.*/addProxyMethod(hashCodeMethod, Object.class);addProxyMethod(equalsMethod, Object.class);addProxyMethod(toStringMethod, Object.class);/** Now record all of the methods from the proxy interfaces, giving* earlier interfaces precedence over later ones with duplicate* methods.*/for (Class<?> intf : interfaces) {for (Method m : intf.getMethods()) {addProxyMethod(m, intf);}}/** For each set of proxy methods with the same signature,* verify that the methods' return types are compatible.*/for (List<ProxyMethod> sigmethods : proxyMethods.values()) {checkReturnTypes(sigmethods);}/* ============================================================* Step 2: Assemble FieldInfo and MethodInfo structs for all of* fields and methods in the class we are generating.*/try {methods.add(generateConstructor());for (List<ProxyMethod> sigmethods : proxyMethods.values()) {for (ProxyMethod pm : sigmethods) {// add static field for method's Method objectfields.add(new FieldInfo(pm.methodFieldName,"Ljava/lang/reflect/Method;",ACC_PRIVATE | ACC_STATIC));// generate code for proxy method and add itmethods.add(pm.generateMethod());}}methods.add(generateStaticInitializer());} catch (IOException e) {throw new InternalError("unexpected I/O Exception", e);}if (methods.size() > 65535) {throw new IllegalArgumentException("method limit exceeded");}if (fields.size() > 65535) {throw new IllegalArgumentException("field limit exceeded");}/* ============================================================* Step 3: Write the final class file.*//** Make sure that constant pool indexes are reserved for the* following items before starting to write the final class file.*/cp.getClass(dotToSlash(className));cp.getClass(superclassName);for (Class<?> intf: interfaces) {cp.getClass(dotToSlash(intf.getName()));}/** Disallow new constant pool additions beyond this point, since* we are about to write the final constant pool table.*/cp.setReadOnly();ByteArrayOutputStream bout = new ByteArrayOutputStream();DataOutputStream dout = new DataOutputStream(bout);try {/** Write all the items of the "ClassFile" structure.* See JVMS section 4.1.*/// u4 magic;dout.writeInt(0xCAFEBABE);// u2 minor_version;dout.writeShort(CLASSFILE_MINOR_VERSION);// u2 major_version;dout.writeShort(CLASSFILE_MAJOR_VERSION);cp.write(dout);             // (write constant pool)// u2 access_flags;dout.writeShort(accessFlags);// u2 this_class;dout.writeShort(cp.getClass(dotToSlash(className)));// u2 super_class;dout.writeShort(cp.getClass(superclassName));// u2 interfaces_count;dout.writeShort(interfaces.length);// u2 interfaces[interfaces_count];for (Class<?> intf : interfaces) {dout.writeShort(cp.getClass(dotToSlash(intf.getName())));}// u2 fields_count;dout.writeShort(fields.size());// field_info fields[fields_count];for (FieldInfo f : fields) {f.write(dout);}// u2 methods_count;dout.writeShort(methods.size());// method_info methods[methods_count];for (MethodInfo m : methods) {m.write(dout);}// u2 attributes_count;dout.writeShort(0); // (no ClassFile attributes for proxy classes)} catch (IOException e) {throw new InternalError("unexpected I/O Exception", e);}return bout.toByteArray();}
}

3.3 查看生成的代理类

在这里插入图片描述

生成代码并且保存在磁盘:

@org.junit.jupiter.api.Test
public void test() {byte[] classFile = ProxyGenerator.generateProxyClass("$proxy0",new Class[]{Shop.class});String path = "/Users/fanjunfu/Downloads/$proxy0.class";try(FileOutputStream fos = new FileOutputStream(path)){fos.write(classFile);fos.flush();System.out.println("generateProxyClass save success");} catch (Exception e){System.out.println("generateProxyClass save fail");}}

将保存在磁盘中的class文件拖拽到IDEA中,进行反编译【通过这里也能看出来,为啥JDK动态代理必须要求被代理对象实现接口】:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//import com.example.demo.inter.Shop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $proxy0 extends Proxy implements Shop {private static Method m1;private static Method m2;private static Method m3;private static Method m0;// 这里的InvocationHandler就是我们实现的InvocationHandlerpublic $proxy0(InvocationHandler var1) throws  {super(var1);}public final boolean equals(Object var1) throws  {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final String toString() throws  {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}// 调用代理对象的sell()方法,其实就是调用InvocationHandler的invoke()方法,这里实现了dispatch.public final void sell() throws  {try {super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws  {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}// 除了自定义的接口,对equals、toString、hashCode方法也进行了代理static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m2 = Class.forName("java.lang.Object").getMethod("toString");m3 = Class.forName("com.example.demo.inter.Shop").getMethod("sell");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}

4、CGLIB

Spring的切面实现除了上述的JDK动态代理,也会使用CGLIB动态代理。如果被代理对象没有实现接口,则就会使用CGLIB【这个是继承被代理对象,创建被代理对象的子类。所以,CGLIB要求被代理对象不能是final的,方法也不能是final】。

4.1 CGLIB的例子

4.1.1 定义目标对象

public class ZhangLiangMaLaTang implements Shop {@Overridepublic void sell() {System.out.println("张亮麻辣烫");}
}

4.1.2 自定义方法拦截器

重写intercept()方法:

public class AttendanceMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("美团欢迎您");Object result = proxy.invokeSuper(obj, args); // 这里会调用目标对象的方法System.out.println("召唤骑手");return result;}
}

4.1.3 使用动态代理

public class CglibProxyTest {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Meituan.class);enhancer.setCallback(new AttendanceMethodInterceptor());// 创建代理对象Object object = enhancer.create();Meituan meituan = (Meituan) object;meituan.sell();}
}

4.2 CGLIB原理

首先我们看到生成的class文件多了五个类:
在这里插入图片描述
重要的是关注上面三个类。
【Meituan$$EnhancerBySpringCGLIB$$b20d6044】类:目标对象的代理类
【Meituan$$EnhancerBySpringCGLIB$$b20d6044$$FastClassBySpringCGLIB$$b7fada0b】类:代理对象的索引类
【Meituan$$FastClassBySpringCGLIB$$90ab0eac】类:目标对象的索引类

cglib会执行到一个重要的方法:

public class MethodProxy {private volatile FastClassInfo fastClassInfo;// 目标方法之前会执行这个方法public Object invoke(Object obj, Object[] args) throws Throwable {try {init();FastClassInfo fci = fastClassInfo;return fci.f1.invoke(fci.i1, obj, args);  // 调用目标索引对象的invoke()}catch (InvocationTargetException ex) {throw ex.getTargetException();}catch (IllegalArgumentException ex) {if (fastClassInfo.i1 < 0)throw new IllegalArgumentException("Protected method: " + sig1);throw ex;}}// 初始化fastClassInfoprivate void init() {if (fastClassInfo == null) {synchronized (initLock) {if (fastClassInfo == null) {CreateInfo ci = createInfo;FastClassInfo fci = new FastClassInfo();fci.f1 = helper(ci, ci.c1); // 目标对象的索引对象:Meituan$$FastClassBySpringCGLIB$$90ab0eacfci.f2 = helper(ci, ci.c2); // 代理对象的索引对象:Meituan$$EnhancerBySpringCGLIB$$b20d6044\$$FastClassBySpringCGLIB$$b7fada0bfci.i1 = fci.f1.getIndex(sig1); // 当前方法在目标对象的索引对象中的索引fci.i2 = fci.f2.getIndex(sig2);  // 当前方法在代理对象的索引对象中的索引fastClassInfo = fci;createInfo = null;}}}}
}

代理对象:

public class Meituan$$EnhancerBySpringCGLIB$$b20d6044 extends Meituan implements SpringProxy, Advised, Factory {final String CGLIB$sell$0() {return super.sell();}public final String sell() {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$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy) : super.sell();}
}

目标对象的索引类:

public class Meituan$$FastClassBySpringCGLIB$$90ab0eac extends FastClass {public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {Meituan var10000 = (Meituan)var2;int var10001 = var1;try {switch (var10001) {case 0:return var10000.sell(); 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 int getIndex(Signature var1) {String var10000 = var1.toString();switch (var10000.hashCode()) {case -16382947:if (var10000.equals("sell()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 class Meituan$$EnhancerBySpringCGLIB$$b20d6044$$FastClassBySpringCGLIB$$b7fada0b extends FastClass {public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {Meituan..EnhancerBySpringCGLIB..b20d6044 var10000 = (Meituan..EnhancerBySpringCGLIB..b20d6044)var2;int var10001 = var1;try {switch (var10001) {case 0:b20d6044.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);return null;case 1:b20d6044.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);return null;case 2:return var10000.getCallbacks();case 3:var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);return null;case 4:var10000.setCallbacks((Callback[])var3[0]);return null;case 5:return var10000.getCallback(((Number)var3[0]).intValue());case 6:return b20d6044.CGLIB$findMethodProxy((Signature)var3[0]);case 7:return var10000.getTargetSource();case 8:return var10000.getTargetClass();case 9:return var10000.getProxiedInterfaces();case 10:return new Boolean(var10000.isInterfaceProxied((Class)var3[0]));case 11:return new Integer(var10000.getAdvisorCount());case 12:return var10000.getAdvisors();case 13:return new Boolean(var10000.isProxyTargetClass());case 14:var10000.setTargetSource((TargetSource)var3[0]);return null;case 15:var10000.setExposeProxy((Boolean)var3[0]);return null;case 16:return new Boolean(var10000.isExposeProxy());case 17:var10000.setPreFiltered((Boolean)var3[0]);return null;case 18:return new Boolean(var10000.isPreFiltered());case 19:var10000.addAdvisor(((Number)var3[0]).intValue(), (Advisor)var3[1]);return null;case 20:var10000.addAdvisor((Advisor)var3[0]);return null;case 21:return new Boolean(var10000.removeAdvisor((Advisor)var3[0]));case 22:var10000.removeAdvisor(((Number)var3[0]).intValue());return null;case 23:return new Boolean(var10000.replaceAdvisor((Advisor)var3[0], (Advisor)var3[1]));case 24:var10000.addAdvice((Advice)var3[0]);return null;case 25:var10000.addAdvice(((Number)var3[0]).intValue(), (Advice)var3[1]);return null;case 26:return new Boolean(var10000.removeAdvice((Advice)var3[0]));case 27:return var10000.toProxyConfigString();case 28:b20d6044.CGLIB$STATICHOOK3();return null;case 29:return var10000.CGLIB$sell$0();case 30:return new Boolean(var10000.CGLIB$equals$1(var3[0]));case 31:return var10000.CGLIB$toString$2();case 32:return new Integer(var10000.CGLIB$hashCode$3());case 33:return var10000.CGLIB$clone$4();case 34:return var10000.sell();case 35:return new Boolean(var10000.equals(var3[0]));case 36:return var10000.toString();case 37:return new Integer(var10000.hashCode());case 38:return var10000.clone();case 39:return new Integer(var10000.indexOf((Advisor)var3[0]));case 40:return new Integer(var10000.indexOf((Advice)var3[0]));case 41:return var10000.newInstance((Callback[])var3[0]);case 42:return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);case 43:return var10000.newInstance((Callback)var3[0]);case 44:return new Boolean(var10000.isFrozen());}} catch (Throwable var4) {throw new InvocationTargetException(var4);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public int getIndex(Signature var1) {String var10000 = var1.toString();switch (var10000.hashCode()) {case -2103996935:if (var10000.equals("isExposeProxy()Z")) {return 16;}break;case -1938347695:if (var10000.equals("getTargetClass()Ljava/lang/Class;")) {return 8;}break;case -1891827894:if (var10000.equals("getProxiedInterfaces()[Ljava/lang/Class;")) {return 9;}break;case -1887170608:if (var10000.equals("getTargetSource()Lorg/springframework/aop/TargetSource;")) {return 7;}break;case -1882565338:if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {return 30;}break;case -1870561232:if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {return 6;}break;case -1745842178:if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {return 4;}break;case -1656914424:if (var10000.equals("indexOf(Lorg/aopalliance/aop/Advice;)I")) {return 40;}break;case -1641413109:if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 41;}break;case -1457476106:if (var10000.equals("CGLIB$STATICHOOK3()V")) {return 28;}break;case -1411842725:if (var10000.equals("CGLIB$hashCode$3()I")) {return 32;}break;case -1378580207:if (var10000.equals("toProxyConfigString()Ljava/lang/String;")) {return 27;}break;case -1127359161:if (var10000.equals("setExposeProxy(Z)V")) {return 15;}break;case -1068101097:if (var10000.equals("setPreFiltered(Z)V")) {return 17;}break;case -1034266769:if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {return 0;}break;case -1025895669:if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {return 1;}break;case -1012917840:if (var10000.equals("addAdvice(ILorg/aopalliance/aop/Advice;)V")) {return 25;}break;case -1006102474:if (var10000.equals("isProxyTargetClass()Z")) {return 13;}break;case -988317324:if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 42;}break;case -980141523:if (var10000.equals("replaceAdvisor(Lorg/springframework/aop/Advisor;Lorg/springframework/aop/Advisor;)Z")) {return 23;}break;case -904152374:if (var10000.equals("removeAdvisor(I)V")) {return 22;}break;case -872603166:if (var10000.equals("removeAdvisor(Lorg/springframework/aop/Advisor;)Z")) {return 21;}break;case -552893142:if (var10000.equals("addAdvisor(ILorg/springframework/aop/Advisor;)V")) {return 19;}break;case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return 38;}break;case -439517399:if (var10000.equals("isPreFiltered()Z")) {return 18;}break;case -434856660:if (var10000.equals("CGLIB$sell$0()Ljava/lang/String;")) {return 29;}break;case -16382947:if (var10000.equals("sell()Ljava/lang/String;")) {return 34;}break;case 103043491:if (var10000.equals("getAdvisorCount()I")) {return 11;}break;case 187947380:if (var10000.equals("setTargetSource(Lorg/springframework/aop/TargetSource;)V")) {return 14;}break;case 610042816:if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 43;}break;case 644726458:if (var10000.equals("isInterfaceProxied(Ljava/lang/Class;)Z")) {return 10;}break;case 1132856532:if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {return 2;}break;case 1238545150:if (var10000.equals("indexOf(Lorg/springframework/aop/Advisor;)I")) {return 39;}break;case 1246779367:if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {return 3;}break;case 1306468936:if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {return 31;}break;case 1364367423:if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {return 5;}break;case 1426835813:if (var10000.equals("addAdvice(Lorg/aopalliance/aop/Advice;)V")) {return 24;}break;case 1636583119:if (var10000.equals("isFrozen()Z")) {return 44;}break;case 1744736673:if (var10000.equals("addAdvisor(Lorg/springframework/aop/Advisor;)V")) {return 20;}break;case 1800494055:if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {return 33;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return 35;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return 36;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return 37;}break;case 2119600998:if (var10000.equals("removeAdvice(Lorg/aopalliance/aop/Advice;)Z")) {return 26;}break;case 2122046924:if (var10000.equals("getAdvisors()[Lorg/springframework/aop/Advisor;")) {return 12;}}return -1;}
}

5、Spring切面

如下Spring AOP使用的是CGLIB。

5.1 定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JDKProxy {
}
@Aspect
@Component
public class JDKProxyAspect {@AfterReturning(value = "@annotation(JDKProxy)", returning = "result")public void after(JoinPoint joinPoint, Object result) throws Throwable {System.out.println("jdk proxy ");}
}

5.2 定义被代理对象

@Component
public class Meituan {@JDKProxypublic String sell() {System.out.println("美团欢迎您");System.out.println("可以选购麻辣烫");  // 调用目标对象【张亮麻辣烫】System.out.println("召唤骑手");return "美团外卖";}
}

5.3 打印CGLIB实现的子类

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/fanjunfu/project/learn/demo/target/classes/"); // 将生成的子类存放到的位置ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);}}

5.4 查询CGLIB生成的子类

去指定的目录【/Users/fanjunfu/project/learn/demo/target/classes/】下面查看相应的子类:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.example.demo.service;import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;public class Meituan$$EnhancerBySpringCGLIB$$c581ba52 extends Meituan implements SpringProxy, Advised, 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 MethodInterceptor CGLIB$CALLBACK_1;private NoOp CGLIB$CALLBACK_2;private Dispatcher CGLIB$CALLBACK_3;private Dispatcher CGLIB$CALLBACK_4;private MethodInterceptor CGLIB$CALLBACK_5;private MethodInterceptor CGLIB$CALLBACK_6;private static Object CGLIB$CALLBACK_FILTER;private static final Method CGLIB$sell$0$Method;private static final MethodProxy CGLIB$sell$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$STATICHOOK3() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class var0 = Class.forName("com.example.demo.service.Meituan$$EnhancerBySpringCGLIB$$c581ba52");Class var1;CGLIB$sell$0$Method = ReflectUtils.findMethods(new String[]{"sell", "()Ljava/lang/String;"}, (var1 = Class.forName("com.example.demo.service.Meituan")).getDeclaredMethods())[0];CGLIB$sell$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "sell", "CGLIB$sell$0");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");}final String CGLIB$sell$0() {return super.sell();}public final String sell() {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$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy) : super.sell();}final boolean CGLIB$equals$1(Object var1) {return super.equals(var1);}public final boolean equals(Object var1) {MethodInterceptor var10000 = this.CGLIB$CALLBACK_5;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_5;}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_6;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_6;}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 -16382947:if (var10000.equals("sell()Ljava/lang/String;")) {return CGLIB$sell$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 final TargetSource getTargetSource() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getTargetSource();}public final Class[] getProxiedInterfaces() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getProxiedInterfaces();}public final boolean isInterfaceProxied(Class var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isInterfaceProxied(var1);}public final int getAdvisorCount() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getAdvisorCount();}public final Advisor[] getAdvisors() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getAdvisors();}public final boolean isProxyTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isProxyTargetClass();}public final void setTargetSource(TargetSource var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setTargetSource(var1);}public final void setExposeProxy(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setExposeProxy(var1);}public final boolean isExposeProxy() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isExposeProxy();}public final void setPreFiltered(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setPreFiltered(var1);}public final boolean isPreFiltered() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isPreFiltered();}public final void addAdvisor(int var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1, var2);}public final void addAdvisor(Advisor var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1);}public final void removeAdvisor(int var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).removeAdvisor(var1);}public final boolean removeAdvisor(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvisor(var1);}public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).replaceAdvisor(var1, var2);}public final void addAdvice(Advice var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1);}public final void addAdvice(int var1, Advice var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1, var2);}public final boolean removeAdvice(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvice(var1);}public final String toProxyConfigString() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).toProxyConfigString();}public final int indexOf(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final int indexOf(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final boolean isFrozen() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isFrozen();}public final Class getTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((TargetClassAware)var10000.loadObject()).getTargetClass();}public Meituan$$EnhancerBySpringCGLIB$$c581ba52() {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) {Meituan$$EnhancerBySpringCGLIB$$c581ba52 var1 = (Meituan$$EnhancerBySpringCGLIB$$c581ba52)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;}}Callback[] var10001 = (Callback[])var10000;var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];}}public Object newInstance(Callback[] var1) {CGLIB$SET_THREAD_CALLBACKS(var1);Meituan$$EnhancerBySpringCGLIB$$c581ba52 var10000 = new Meituan$$EnhancerBySpringCGLIB$$c581ba52();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Callback var1) {throw new IllegalStateException("More than one callback object required");}public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {CGLIB$SET_THREAD_CALLBACKS(var3);Meituan$$EnhancerBySpringCGLIB$$c581ba52 var10000 = new Meituan$$EnhancerBySpringCGLIB$$c581ba52;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);Object var10000;switch (var1) {case 0:var10000 = this.CGLIB$CALLBACK_0;break;case 1:var10000 = this.CGLIB$CALLBACK_1;break;case 2:var10000 = this.CGLIB$CALLBACK_2;break;case 3:var10000 = this.CGLIB$CALLBACK_3;break;case 4:var10000 = this.CGLIB$CALLBACK_4;break;case 5:var10000 = this.CGLIB$CALLBACK_5;break;case 6:var10000 = this.CGLIB$CALLBACK_6;break;default:var10000 = null;}return (Callback)var10000;}public void setCallback(int var1, Callback var2) {switch (var1) {case 0:this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;break;case 1:this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;break;case 2:this.CGLIB$CALLBACK_2 = (NoOp)var2;break;case 3:this.CGLIB$CALLBACK_3 = (Dispatcher)var2;break;case 4:this.CGLIB$CALLBACK_4 = (Dispatcher)var2;break;case 5:this.CGLIB$CALLBACK_5 = (MethodInterceptor)var2;break;case 6:this.CGLIB$CALLBACK_6 = (MethodInterceptor)var2;}}public Callback[] getCallbacks() {CGLIB$BIND_CALLBACKS(this);return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5, this.CGLIB$CALLBACK_6};}public void setCallbacks(Callback[] var1) {this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];this.CGLIB$CALLBACK_2 = (NoOp)var1[2];this.CGLIB$CALLBACK_3 = (Dispatcher)var1[3];this.CGLIB$CALLBACK_4 = (Dispatcher)var1[4];this.CGLIB$CALLBACK_5 = (MethodInterceptor)var1[5];this.CGLIB$CALLBACK_6 = (MethodInterceptor)var1[6];}static {CGLIB$STATICHOOK3();}
}

http://www.mrgr.cn/news/67569.html

相关文章:

  • 《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
  • 2021 数二真题
  • 约瑟夫环问题——4个解法总结(C语言)
  • WebGUI之Gradio:Gradio 5的简介、安装和使用方法、案例应用之详细攻略
  • 使用 ABAP GIT 发生 IF_APACK_MANIFEST dump
  • [Web安全 网络安全]-学习文章汇总导航(持续更新中)
  • 22.04Ubuntu---ROS2使用rclcpp编写节点
  • 积极助力信创工作,爱加密荣获麒麟系统优秀合作伙伴
  • EFI和UEFI的起源及Romstage和Ramstage有什么区别?
  • Certimate:又发现了一款不错的自动化SSL证书管理工具,它能让你的网站随时保持https安全状态,抓紧收藏起来吧
  • Windows系统中Oracle VM VirtualBox的安装
  • 探索魁北克:IT精英的理想移民地
  • 书生第四期实训营基础岛——L1G5000 XTuner 微调个人小助手认知
  • 《重学Java设计模式》之 工厂方法模式
  • 以梧桐数据库为例分析分组排序并取每组第二大数值对应的用户的SQL实现
  • C#的IDisposable 接口和析构函数
  • JS保留两位小数
  • 我们来学mysql -- EXPLAIN之ID(原理篇)
  • idea-git 远程仓库代码回滚,本地仓库代码回滚,删除未加入git的文件
  • 二叉树及其应用
  • 背包九讲——背包问题求具体方案
  • 三品PLM系统如何规范企业图纸文档资料电子化管理
  • 全国消防安全月知识答题小程序来袭
  • 基于SpringBoot的Java教学支持系统开发指南
  • 将python代码转化成接口api
  • 低价治理都有哪些方法