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.xdnf.cn/news/10947.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

多线程的创建方式以及及Thread类详解

目录 一.线程的创建方法&#xff1a;&#xff08;重点&#xff09; 一&#xff1a;继承Thread类 写法一&#xff1a;正常写法 写法二&#xff1a;匿名内部类 二.实现Runnable接口 写法一&#xff1a;正常写法 写法二&#xff1a;匿名内部类 三. 实现 Callable 接口 ​…

408最后冲刺阶段,怎么做题才能考到120+?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 重要性排序如下&#xff1a;真题占据首位&#xff0c;紧随其后的是王道模拟题&#xff0c;王道书与题目则紧随其后&#xff0c;而408统考配套习题&#xff08;高教版&#xff09;与之大致相当。 真题&#xff0c;无疑…

如何对接低价又稳定的影视会员渠道?

对接低价折扣影视会员渠道通常涉及到与影视内容提供商或第三方分销商的合作。以下是一些基本步骤和注意事项&#xff0c;帮助你顺利对接这类渠道&#xff1a; 1. 市场调研 了解市场&#xff1a;研究市场上现有的影视会员服务提供商&#xff0c;包括价格、服务、用户反馈等。确…

crond 任务调度 (Linux相关指令:crontab)

相关视频链接 crontab 进行 定时任务 的设置 概述 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序 任务调度的分类&#xff1a; 1.系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等。 2.个别用户可能希望执行某些程序&#xff0c;比如…

顺序表+ArrayList

文章目录 一、基础知识1.1 数据结构类的继承图1.2 List 介绍1.3 线性表 二、数据结构 -- 顺序表2.1 什么是顺序表以及优缺点2.2 用数组实现顺序表细节解析代码 三、ArrayList3.1 Java中如何使用ArrayList3.2 ArrayList源码无参构造方法add方法扩容方法指定初始容量构造利用其他…

【工具变量】排污权交易政策试点DID(2000-2023)

数据简介&#xff1a;在过去几十年间的“高增长、高能耗、高污染”的经济发展背景下&#xff0c;随着社会各界不断反应高经济增长背后付出的巨大环境代价&#xff0c;中国ZF将节能环保减排纳入长期规划治理中。在2007年&#xff0c;我国开始启动了二氧化硫&#xff08;SO2&…

通用特效Shader

一、通用特效Shader介绍 1.1 什么是通用特效材质 Unity支持SRP Batcher后&#xff0c;使用UberShader的优势非常明显。所谓&#xff0c;UberShader&#xff0c;即一个超级Shader&#xff0c;覆盖一类功能&#xff0c;而不是多个分散的小Shader&#xff0c;比如一个通用特效Sh…

网络安全SQL初步注入2

六.报错注入 mysql函数 updatexml(1,xpath语法,0) xpath语法常用concat拼接 例如: concat(07e,(查询语句),07e) select table_name from information_schema.tables limit 0,1 七.宽字节注入(如果后台数据库的编码为GBK) url编码:为了防止提交的数据和url中的一些有特殊意…

Golang--面向对象

Golang语言面向对象编程说明&#xff1a; Golang也支持面向对象编程(OOP)&#xff0c;但是和传统的面向对象编程有区别&#xff0c;并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。Golang没有类(class)&#xff0c;Go语言的结构体(struct)和其…

英国留学论文写作中复合句式基础知识讲解

从句子的结构出发&#xff0c;复合句式是将两个以上的独立、完整的字句子通过coordinating conjunction或者分号连接在一起。因此&#xff0c;复合句式可以理解成为两个以上的简单句子组合在一起。下面英国翰思教育通过举例的方式&#xff0c;来介绍如何将独立的句子连接在一起…

从奇富科技,QQ钱包看信贷服务、贷款超市的的客户注册认证流程有什么不同

概览 奇富科技作为港股信贷第一企业&#xff0c;目前已服务2.4亿用户&#xff0c;是国内头部信贷科技服务平台。 QQ钱包&#xff0c;作为8亿用户的贷款超市&#xff0c;拥有其他贷款超市产品梦寐以求的流量入口。 产品模式 奇富科技作为信贷科技服务平台&#xff0c;主要提…

寻找伤感短视频素材 这些网站帮你轻松下载无水印资源

无论是制作情感类短视频&#xff0c;还是为抖音视频寻找合适的素材&#xff0c;伤感视频素材一直是创作者们关注的重点。如果你正在为如何找到高质量的伤感素材而困扰&#xff0c;那么今天我将推荐一些非常实用的素材网站&#xff0c;帮助你快速找到适合的伤感视频素材&#xf…

Java项目实战II基于Spring Boot的大学生智能消费记账系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当今社会…

Linux 抓包工具 --- tcpdump

序言 在传输层 Tcp 的学习中&#xff0c;我们了解了 三次握手和四次挥手 的概念&#xff0c;但是看了这么多篇文章&#xff0c;我们也只是停留在 纸上谈兵。  欲知事情如何&#xff0c;我们其实可以尝试去看一下具体的网络包的信息。在这篇文章中将向大家介绍&#xff0c;在 L…

基于Spring Boot+Vue的养老院管理系统【原创】

一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框架Vue.js&#xff1b;UI库&#xff1a;ElementUI&#xff1b; 开发工具&…

基于SpringBoot+Vue音乐播放和推荐系统【提供源码+答辩PPT+参考文档+项目部署】

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

震撼!通过双重异步,Excel 10万行数据导入从191秒优化到2秒!

震撼&#xff01;通过双重异步&#xff0c;Excel 10万行数据导入从191秒优化到2秒&#xff01; 在现代的企业级应用开发中&#xff0c;海量数据的处理效率和并发性能优化是一个非常重要的课题。无论是大规模数据导入、文件解析&#xff0c;还是在分布式系统中处理高并发任务&a…

Linux编程:用于调试 C、C++ 和其他编程语言编写的程序的调试工具GDB的使用

目录 一、概述 二、 安装GDB 三、准备程序 四、使用GDB 1、启动GDB 2、获取帮助 五、 常用GDB命令 六、示例调试会话 七、其他事项 一、概述 GDB&#xff08;GNU Debugger&#xff09;是一个非常强大的调试工具&#xff0c;广泛用于调试 C、C 和其他编程语言编写的程序…

书生实战营第四期-基础岛第五关-XTuner 微调个人小助手认知

基础任务 使用 XTuner 微调 InternLM2-Chat-7B 实现自己的小助手认知 一、环境配置与数据准备 1.构建虚拟环境 cd ~ #git clone 本repo git clone https://github.com/InternLM/Tutorial.git -b camp4 mkdir -p /root/finetune && cd /root/finetune conda create -…

java day04-面向对象基础(内存 封装 继承 修饰符 工具类 )

1.对象内存图 1.1 Java 内存分配 1.2 堆和栈 栈:所有局部变量都会在栈内存中创建 局部变量&#xff1a;定义在方法中的变量或者方法声明上的变量 方法执行都会加载到栈中进行 -----------------------------------------------------------------------------------------…