JDK和CGLIB动态代理原理

JDK动态代理原理解析

一、例子:

1、定义基础接口
public interface HttpApi {
    String get(String url);
}
2、实现类
public class RealModule implements HttpApi {
     @Override
     public String get(String url) {
         return "result";
     }
}
3、动态代理
public class ProxyFactory {
    public static HttpApi getProxy(HttpApi target) {
        return (HttpApi) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new LogHandler(target));
    }

    // 增强类
    private static class LogHandler implements InvocationHandler {
        private HttpApi target;

        LogHandler(HttpApi target) {
            this.target = target;
        }
        // method底层的方法无参数时,args为空或者长度为0
        @Override
        public Object invoke(Object proxy, Method method, @Nullable Object[] args)       
               throws Throwable {
            // 扩展的功能
            Log.i("http-statistic", (String) args[0]);
            // 访问基础对象
            return method.invoke(target, args);
        }
    }
}

上面例子中出现的核心方法有:

  • Proxy.newProxyInstance( target.getClass().getClassLoader(),target.getClass().getInterfaces(),new LogHandler(target));
  • 参数说明:1.类加载器。2.指定newProxyInstance()方法返回的对象要实现哪些接口,可以指定多个接口。3.调用处理器,实现了InvocationHandler接口的实现类,重写invoke方法来增强被代理类的方法。
  • 方法返回:实现了指定接口的实现类对象,即被代理类。
  • invoke(Object proxy, Method method, @Nullable Object[] args) ;
  • 参数说明:1.代理对象,也就是Proxy.newProxyInstance()方法返回的对象。2.被代理对象的方法如例子中的get()方法。3.表示当前被调用方法的参数。
  • 方法返回:前被调用的方法的返回值,没有返回值则返回null。

二、反编译代理类源码

public final class $proxy0 extends Proxy implements HttpApi {
    //反射的元数据Method存储起来,避免重复创建
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    /**
     * Object#hashCode()
     * Object#equals(Object)
     * Object#toString()
     */

    // 实现了HttpApi接口
    public final String get() throws  {
        try {
            //转发到Invocation#invoke()
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            //Object#hashCode()
            //Object#equals(Object)
            //Object#toString()
            m3 = Class.forName("HttpApi").getMethod("get");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

通过反编译的源码我们可以得到以下结论:

  • JDK动态代理生成了代理类(继承Proxy)的字节码文件(Class)。
  • 代理类继承自 java.lang.reflect.Proxy,实现了HttpApi接口。
  • 代理类中的所有方法都是final 的。
  • 代理类所有的方法功能的实现都统一调用了InvocationHandler的invoke()方法。
  • 通过(String)super.h.invoke(this, m3, (Object[])null)方法进入增强类以实现对被代理方法的增强。
  • JDK动态代理只能对实现了接口的类进行代理,不能对普通类进行代理,这是因为JDK动态代理生成的新的代理类其父类是Proxy,java不支持类的多继承,所以只能实现接口。

三、核心类Proxy源码解析

1.JDK动态代理核心类:Proxy。

2.Proxy主要API

方法描述
getProxyClass(ClassLoader, Class<?>...) : Class<?>获取实现目标接口的代理类 Class 对象
newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h): Object获取实现目标接口的代理对象
isProxyClass(Class<?>) : boolean判断一个 Class 对象是否属于代理类
getInvocationHandler(Object) : InvocationHandler获取代理对象内部的 InvocationHandler

3.核心源码:

3.1 Proxy.java

1、获取代理类 Class 对象
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces){
    final Class<?>[] intfs = interfaces.clone();
    ...
    1.1 获得代理类 Class 对象
    return getProxyClass0(loader, intfs);
}

2、实例化代理类对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
    ...
    final Class<?>[] intfs = interfaces.clone();
    2.1 获得代理类 Class对象
    Class<?> cl = getProxyClass0(loader, intfs);
    ...
    2.2 获得代理类构造器 (接收一个 InvocationHandler 参数)
    // private static final Class<?>[] constructorParams = { InvocationHandler.class };
    final Constructor<?> cons = cl.getConstructor(constructorParams);
    final InvocationHandler ih = h;
    ...
    2.3 反射创建实例
    return newInstance(cons, ih);
}

可以看到,实例化代理对象也需要先通过 getProxyClass0(...) 获取代理类 Class 对象,而 newProxyInstance(...) 随后会获取参数为 InvocationHandler 的构造函数实例化一个代理类对象。

3.2获取代理类的Class对象

-> 1.1、2.1 获得代理类 Class对象
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
    ...
    从缓存中获取代理类,如果缓存未命中,则通过ProxyClassFactory生成代理类
    return proxyClassCache.get(loader, interfaces);
}

private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>>{

    3.1 代理类命名前缀
    private static final String proxyClassNamePrefix = "$Proxy";

    3.2 代理类命名后缀,从 0 递增(原子 Long)
    private static final AtomicLong nextUniqueNumber = new AtomicLong();

    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        3.3 参数校验
        for (Class<?> intf : interfaces) {
            // 验证参数 interfaces 和 ClassLoder 中加载的是同一个类
            // 验证参数 interfaces 是接口类型
            // 验证参数 interfaces 中没有重复项
            // 否则抛出 IllegalArgumentException
        }
        // 验证所有non-public接口来自同一个包

        3.4(一般地)代理类包名
        // public static final String PROXY_PACKAGE = "com.sun.proxy";
        String proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";

        3.5 代理类的全限定名
        long num = nextUniqueNumber.getAndIncrement();
        String proxyName = proxyPkg + proxyClassNamePrefix + num;

        3.6 生成字节码数据
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);

        3.7 从字节码生成 Class 对象
        return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length); 
    }
}

-> 3.6 生成字节码数据
public static byte[] generateProxyClass(final String var0, Class[] var1) {
    ProxyGenerator var2 = new ProxyGenerator(var0, var1);
    ...
    final byte[] var3 = var2.generateClassFile();
    return var3;
}

3.3ProxyGenerator.java

生成class文件字节码

private byte[] generateClassFile() {
    3.6.1 只代理Object的hashCode、equals和toString
    this.addProxyMethod(hashCodeMethod, Object.class);
    this.addProxyMethod(equalsMethod, Object.class);
    this.addProxyMethod(toStringMethod, Object.class);

    3.6.2 代理接口的每个方法
    ...
    for(var1 = 0; var1 < this.interfaces.length; ++var1) {
        ...
    }
    
    3.6.3 添加带有 InvocationHandler 参数的构造器
    this.methods.add(this.generateConstructor());
    var7 = this.proxyMethods.values().iterator();
    while(var7.hasNext()) {
        ...
        3.6.4 在每个代理的方法中调用InvocationHandler#invoke()
    }

    3.6.5 输出字节流
    ByteArrayOutputStream var9 = new ByteArrayOutputStream();
    DataOutputStream var10 = new DataOutputStream(var9);
    ...
    return var9.toByteArray();
}

核心流程:JDK 动态代理生成的代理类命名为 com.sun.proxy$Proxy[从0开始的数字](例如:com.sun.proxy$Proxy0),这个类继承自 java.lang.reflect.Proxy。其内部还有一个参数为 InvocationHandler 的构造器,对于代理接口的方法调用都会分发到 InvocationHandler#invoke()。

CGLIB动态代理原理解析

一、例子

// 被代理类
public class PersonService {
    public PersonService() {
        System.out.println("PersonService构造");
    }
    // 该方法不能被子类覆盖
    // Cglib是无法代理final修饰的方法的,具体原因我们一会通过源码来分析
    final public Person getPerson(String code) {
        System.out.println("PersonService:getPerson>>"+code);
        return null;
    }

    public void setPerson() {
        System.out.println("PersonService:setPerson");
    }
}
// 增强类
public class CglibProxyIntercepter implements MethodInterceptor {
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前...");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("执行后...");
        return object;
    }
}
// 测试类
public class Test {
    public static void main(String[] args) {
        //代理类class文件存入本地磁盘
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(PersonService.class);
        enhancer.setCallback(new CglibProxyIntercepter());
        PersonService proxy= (PersonService)  enhancer.create();
        proxy.setPerson();
        proxy.getPerson("1"); 
    } 
}

上面例子中出现的核心方法有:

  • intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy)
  • 参数说明:1.cglib生成的代理对象。2.被代理对象方法。3.方法参数。4.代理方法
  • enhancer.setSuperclass(PersonService.class);
  • enhancer.setCallback(new CglibProxyIntercepter());
  • enhancer.create();
  • 参数说明:1.setSuperclass(PersonService.class);设置被代理类。2.设置增强类。3.创建

二、反编译代理类源码

通过CGLIB会生成三个Class文件,分别是代理类的FastClass,代理类,被代理类的FastClass

2.1就是cglib生成的代理类,它继承了PersonService类,并实现了Factory接口。 

public class PersonService$$EnhancerByCGLIB$$eaaaed75extends PersonService
  implements Factory
{
  private boolean CGLIB$BOUND;
  private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
  private static final Callback[] CGLIB$STATIC_CALLBACKS;
  private MethodInterceptor CGLIB$CALLBACK_0;//拦截器
  private static final Method CGLIB$setPerson$0$Method;//被代理方法
  private static final MethodProxy CGLIB$setPerson$0$Proxy;//代理方法
  private static final Object[] CGLIB$emptyArgs;
  private static final Method CGLIB$finalize$1$Method;
  private static final MethodProxy CGLIB$finalize$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 localClass1 = Class.forName("com.demo.proxy.cglib.PersonService$$EnhancerByCGLIB$$eaaaed75");//代理类
    Class localClass2;//被代理类PersionService
    Method[] tmp95_92 = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
    CGLIB$finalize$1$Method = tmp95_92[0];
    CGLIB$finalize$1$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "finalize", "CGLIB$finalize$1");
    Method[] tmp115_95 = tmp95_92;
    CGLIB$equals$2$Method = tmp115_95[1];
    CGLIB$equals$2$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
    Method[] tmp135_115 = tmp115_95;
    CGLIB$toString$3$Method = tmp135_115[2];
    CGLIB$toString$3$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
    Method[] tmp155_135 = tmp135_115;
    CGLIB$hashCode$4$Method = tmp155_135[3];
    CGLIB$hashCode$4$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$4");
    Method[] tmp175_155 = tmp155_135;
    CGLIB$clone$5$Method = tmp175_155[4];
    CGLIB$clone$5$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
    tmp175_155;
    Method[] tmp223_220 = ReflectUtils.findMethods(new String[] { "setPerson", "()V" }, (localClass2 = Class.forName("com.demo.proxy.cglib.PersonService")).getDeclaredMethods());
    CGLIB$setPerson$0$Method = tmp223_220[0];
    CGLIB$setPerson$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "setPerson", "CGLIB$setPerson$0");
    tmp223_220;
    return;
  }

通过代理类的源码可以看到,代理类会获得所有在父类继承来的方法,并且会有MethodProxy与之对应,比如 Method:CGLIB$setPerson$0$Method,MethodProxy:CGLIB$setPerson$0$Proxy。

2.2方法调用

//代理方法(methodProxy.invokeSuper会调用)   
final void CGLIB$setPerson$0() {
      super.setPerson();
   }
   //被代理方法(methodProxy.invoke会调用,这就是为什么在拦截器中调用methodProxy.invoke会死循环,一直在调用拦截器)
   public final void setPerson() {
      MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
      if(this.CGLIB$CALLBACK_0 == null) {
         CGLIB$BIND_CALLBACKS(this);
         var10000 = this.CGLIB$CALLBACK_0;
      }

      if(var10000 != null) {         
          //调用拦截器
         var10000.intercept(this, CGLIB$setPerson$0$Method, CGLIB$emptyArgs, CGLIB$setPerson$0$Proxy);
      } else {
          // 如果找不到callback实例则直接调用被代理的方法
         super.setPerson(); 
      }
   }

调用过程:代理对象调用this.setPerson()方法 -> 调用拦截器 -> var10000.intercept() -> methodProxy.invokeSuper()  -> CGLIB$setPerson$0() -> 被代理对象setPerson()方法。

如果增强类中增强方法写成

// 增强类
public class CglibProxyIntercepter implements MethodInterceptor {
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行前...");
        Object object = methodProxy.invoke(sub, objects);
        System.out.println("执行后...");
        return object;
    }
}

则调用过程:代理对象调用this.setPerson()方法 -> 调用拦截器 -> var10000.intercept() -> methodProxy.invoke()  -> 代理对象调用this.setPerson()方法 -> 进入死循环

2.3MethodProxy

在拦截器MethodInterceptor中intercept()方法就是调用methodProxy.invokeSuper(),进而调用代理方法CGLIB$setPerson$0(),MethodProxy非常关键,我们分析一下它具体做了什么。

2.3.1MethodProxy.create(localClass2, localClass1, "()V", "setPerson", "CGLIB$setPerson$0");

public class MethodProxy {
    private Signature sig1;
    private Signature sig2;
    private MethodProxy.CreateInfo createInfo;
    private final Object initLock = new Object();
    private volatile MethodProxy.FastClassInfo fastClassInfo;
    //c1:被代理对象Class    
    //c2:代理对象Class    
    //desc:入参类型    
    //name1:被代理方法名    
    //name2:代理方法名
    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
        MethodProxy proxy = new MethodProxy();
        proxy.sig1 = new Signature(name1, desc);//被代理方法签名
        proxy.sig2 = new Signature(name2, desc);//代理方法签名
        proxy.createInfo = new MethodProxy.CreateInfo(c1, c2);
        return proxy;
    }

// 给CreateInfo赋值
private static class CreateInfo {
        //c1:被代理对象Class    
        //c2:代理对象Class    
        Class c1;
        Class c2;
        NamingPolicy namingPolicy;
        GeneratorStrategy strategy;
        boolean attemptLoad;

        public CreateInfo(Class c1, Class c2) {
            this.c1 = c1;
            this.c2 = c2;
            AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
            if (fromEnhancer != null) {
                this.namingPolicy = fromEnhancer.getNamingPolicy();
                this.strategy = fromEnhancer.getStrategy();
                this.attemptLoad = fromEnhancer.getAttemptLoad();
            }

        }
    }

2.3.2通过CreateInfo初始化FastClassInfo

private void init() {
        if (this.fastClassInfo == null) {
            synchronized(this.initLock) {
                if (this.fastClassInfo == null) {
                    CreateInfo ci = this.createInfo;
                    FastClassInfo fci = new FastClassInfo();
                    fci.f1 = helper(ci, ci.c1);
                    fci.f2 = helper(ci, ci.c2);
                    fci.i1 = fci.f1.getIndex(this.sig1);
                    fci.i2 = fci.f2.getIndex(this.sig2);
                    this.fastClassInfo = fci;
                    this.createInfo = null;
                }
            }
        }

    }

private static FastClass helper(CreateInfo ci, Class type) {
        FastClass.Generator g = new FastClass.Generator();
        g.setType(type);
        g.setClassLoader(ci.c2.getClassLoader());
        g.setNamingPolicy(ci.namingPolicy);
        g.setStrategy(ci.strategy);
        g.setAttemptLoad(ci.attemptLoad);
        return g.create();
    }

private static class FastClassInfo {
        FastClass f1;// 被代理类FastClass
        FastClass f2;// 代理类FastClass
        int i1;
        int i2;

        private FastClassInfo() {
        }
    }

2.3.3methodProxy.invoke()与methodProxy.invokeSuper()方法调用

public Object invoke(Object obj, Object[] args) throws Throwable {
        try {
            this.init();
            FastClassInfo fci = this.fastClassInfo;
            // f1被代理类FastClass,被代理类调用invoke方法即调用setPerson()
            return fci.f1.invoke(fci.i1, obj, args);
        } catch (InvocationTargetException var4) {
            throw var4.getTargetException();
        } catch (IllegalArgumentException var5) {
            if (this.fastClassInfo.i1 < 0) {
                throw new IllegalArgumentException("Protected method: " + this.sig1);
            } else {
                throw var5;
            }
        }
    }

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            this.init();
            FastClassInfo fci = this.fastClassInfo;
            // f2代理类FastClass,代理类调用invoke方法即调用CGLIB$setPerson$0()代理方法
            return fci.f2.invoke(fci.i2, obj, args);
        } catch (InvocationTargetException var4) {
            throw var4.getTargetException();
        }
    }

上面代码调用过程就是获取到代理类对应的FastClass,并执行了代理方法。还记得之前生成三个class文件吗?PersonService$EnhancerByCGLIB$eaaaed75$FastClassByCGLIB$$355cb7ea.class就是代理类的FastClass,
PersonService$FastClassByCGLIB$a076b035.class就是被代理类的FastClass。

 2.4FastClass机制

Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。
这个index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比JDK动态代理通过反射调用高。下面我们反编译一个FastClass看看:

//根据方法签名获取index 
public int getIndex(Signature var1) {
      String var10000 = var1.toString();
      switch(var10000.hashCode()) {
      case -2077043409:
         if(var10000.equals("getPerson(Ljava/lang/String;)Lcom/demo/pojo/Person;")) {
            return 21;
         }
         break;
      case -2055565910:
         if(var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
            return 12;
         }
         break;
      case -1902447170:
         if(var10000.equals("setPerson()V")) {
            return 7;
         }
         break;
 //省略部分代码.....  
 //根据index直接定位执行方法
 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
      eaaaed75 var10000 = (eaaaed75)var2;
      int var10001 = var1;

      try {
         switch(var10001) {
         case 0:
            return new Boolean(var10000.equals(var3[0]));
         case 1:
            return var10000.toString();
         case 2:
            return new Integer(var10000.hashCode());
         case 3:
            return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
         case 4:
            return var10000.newInstance((Callback)var3[0]);
         case 5:
            return var10000.newInstance((Callback[])var3[0]);
         case 6:
            var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
            return null;
         case 7:
            var10000.setPerson();
            return null;
         case 8:
            var10000.setCallbacks((Callback[])var3[0]);
            return null;
         case 9:
            return var10000.getCallback(((Number)var3[0]).intValue());
         case 10:
            return var10000.getCallbacks();
         case 11:
            eaaaed75.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
            return null;
         case 12:
            eaaaed75.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
            return null;
         case 13:
            return eaaaed75.CGLIB$findMethodProxy((Signature)var3[0]);
         case 14:
            return var10000.CGLIB$toString$3();
         case 15:
            return new Boolean(var10000.CGLIB$equals$2(var3[0]));
         case 16:
            return var10000.CGLIB$clone$5();
         case 17:
            return new Integer(var10000.CGLIB$hashCode$4());
         case 18:
            var10000.CGLIB$finalize$1();
            return null;
         case 19:
            var10000.CGLIB$setPerson$0();
            return null;
        //省略部分代码....
      } catch (Throwable var4) {
         throw new InvocationTargetException(var4);
      }

      throw new IllegalArgumentException("Cannot find matching method/constructor");
   }

可以看到,该类中大部分都是 switch-case 块,该类通过为方法的调用添加基于整数数字的索引,来减少反射调用的时间,从而将反射调用转化为直接调用

invoke() 方法的使用流程如下:

  • 通过 MethodProxy#init() 方法,用当前方法的 Signature 签名构建两个 FastClass 实例和当前方法对应的 index,并存放在 FastClassInfo 中。
  • 通过 FastClassInfo 中的 FastClass 实例和 index,在 FastClass 中找到对应的方法(在基于整数索引 index 的 switch-case 中查找)进行直接调用。

FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy invoke/invokeSuper时生成的并放在了缓存中。

//MethodProxy invoke/invokeSuper都调用了init()
private void init() {
        if(this.fastClassInfo == null) {
            Object var1 = this.initLock;
            synchronized(this.initLock) {
                if(this.fastClassInfo == null) {
                    MethodProxy.CreateInfo ci = this.createInfo;
                    MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
                    fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass
                    fci.f2 = helper(ci, ci.c2);
                    fci.i1 = fci.f1.getIndex(this.sig1);//获取方法的index
                    fci.i2 = fci.f2.getIndex(this.sig2);
                    this.fastClassInfo = fci;
                    this.createInfo = null;
                }
            }
        }

    }

CGLIB与JDK动态代理之间的区别

1.JDK动态代理只能对实现了接口的类进行代理,不能对普通类进行代理,这是因为JDK动态代理生成的新的代理类其父类是Proxy,java不支持类的多继承,所以只能实现接口。

2.CGLIB能够代理接口和普通类,但是被代理的类不能被final修饰,且接口中的方法不能使用final修饰

3.JDK动态代理使用Java反射技术进行操作,在生成类上效率更高

4.CGLIB使用ASM框架直接对字节码进行修改,使用了FastClass的特性。在某些情况下,类的方法执行会比较高效。

参考:Cglib动态代理实现原理 - 两条闲鱼 - 博客园https://www.jianshu.com/p/5b123443c114CGLIB 动态代理及其原理分析_wadreamer的博客-CSDN博客_cglib动态代理实现原理


版权声明:本文为m0_38033199原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。