动态代理:Cglib原理讲解

简介: 动态代理:Cglib原理讲解

前言

CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。生成的代理类会继承被代理类,并重载其所有的方法。使用Cglib代理会生成三个代理类,继承目标类的代理类、继承FastClass的目标类、继承FastClss的代理类。

正文

我们要想了解其原理,先从生成的代理文件入手,看其结构特点。

测试用例

编写目标类(被代理类)

public class Book {
  public void read(){
    System.out.println("read");
  }
}


自定义方法拦截器

public class MyCglib implements MethodInterceptor {
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("增强");
    Object o1 = methodProxy.invokeSuper(o, objects);
    return o1;
  }
}
public class CglibTest {
  public static void main(String[] args) {
    //指定代理文件生成位置
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:");
    //通过Cglib
    Enhancer enhancer=new Enhancer();
    //设置父类类型
    enhancer.setSuperclass(Book.class);
    //设置回调接口
    enhancer.setCallback(new MyCglib());
    Book o = (Book) enhancer.create();
    o.read();
  }
}

结果分析

运行以上测试用例后,查看生成的类目录,可以看到生成了3个.class字节码代理文件。

代理类:

import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class Book$$EnhancerByCGLIB$$7c19c0f5 extends Book implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$read$0$Method;
    private static final MethodProxy CGLIB$read$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$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("proxy.cglib.Book$$EnhancerByCGLIB$$7c19c0f5");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$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");
        CGLIB$read$0$Method = ReflectUtils.findMethods(new String[]{"read", "()V"}, (var1 = Class.forName("proxy.cglib.Book")).getDeclaredMethods())[0];
        CGLIB$read$0$Proxy = MethodProxy.create(var1, var0, "()V", "read", "CGLIB$read$0");
    }
    final void CGLIB$read$0() {
        super.read();
    }
    public final void read() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        if (var10000 != null) {
            var10000.intercept(this, CGLIB$read$0$Method, CGLIB$emptyArgs, CGLIB$read$0$Proxy);
        } else {
            super.read();
        }
    }
    final boolean CGLIB$equals$1(Object var1) {
        return super.equals(var1);
    }
    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }
    final String CGLIB$toString$2() {
        return super.toString();
    }
    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    }
    final int CGLIB$hashCode$3() {
        return super.hashCode();
    }
    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }
    final Object CGLIB$clone$4() throws CloneNotSupportedException {
        return super.clone();
    }
    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    }
    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$4$Proxy;
            }
            break;
        case 1080349215:
            if (var10000.equals("read()V")) {
                return CGLIB$read$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 Book$$EnhancerByCGLIB$$7c19c0f5() {
        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) {
        Book$$EnhancerByCGLIB$$7c19c0f5 var1 = (Book$$EnhancerByCGLIB$$7c19c0f5)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }
    }
    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }
    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }
        return var10000;
    }
    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }
    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }
    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }
    static {
        CGLIB$STATICHOOK1();
    }
}

目标类FastClass:

import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;
public class Book$$FastClassByCGLIB$$236a9cb6 extends FastClass {
    public Book$$FastClassByCGLIB$$236a9cb6(Class var1) {
        super(var1);
    }
    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case 1080349215:
            if (var10000.equals("read()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 1;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 2;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 3;
            }
        }
        return -1;
    }
    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 2;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 1;
                    }
                }
            }
            break;
        case 3496342:
            if (var1.equals("read")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
        }
        return -1;
    }
    public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }
    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        Book var10000 = (Book)var2;
        int var10001 = var1;
        try {
            switch(var10001) {
            case 0:
                var10000.read();
                return null;
            case 1:
                return new Boolean(var10000.equals(var3[0]));
            case 2:
                return var10000.toString();
            case 3:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }
        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        Book var10000 = new Book;
        Book var10001 = var10000;
        int var10002 = var1;
        try {
            switch(var10002) {
            case 0:
                var10001.<init>();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }
        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
    public int getMaxIndex() {
        return 3;
    }
}

1、我们可以看到代理类中拥有被代理类的所有的方法,在代理类被实例化后后执行静态代码块的内容,会对被代理类的每个方法进行解析,计算出代理类和被代理类方法名称的Signature值,并封装成MethodProxy对象;

创建MethodProxy过程见方法1详解

创建代理类过程见方法4详解


2、在代理类的方法里面会调用我们自定义的方法拦截器,并把代理类对象、方法名称解析对应的MethodProxy、方法对象传递进去,最终由自定义方法拦截器来调用。


3、自定义方法拦截器中的intercept方法,我们可以根据传递进来的MethodProxy决定调用逻辑,如MethodProxy的invokeSuper会调用父类方法。


4、MethodProxy的invokeSuper方法(见方法2详解)会传递代理类对象及其要执行对应方法参数。invokeSuper流程中会生成继承FastClass的被代理类跟代理类共两个.class文件。其中有两个重要的方法getIndex和invoke方法;


5、getIndex方法会根据步骤1中方法名计算出Signature来匹配方法对应的key,根据key去匹配invoke方法决定最终调用哪个方法。这个步骤没有涉及反射也是与JDK动态代理不同的地方。

方法1:MethodProxy类的create方法

  public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    MethodProxy proxy = new MethodProxy();
    //计算的是被代理类的
    proxy.sig1 = new Signature(name1, desc);
    //计算的是代理类的
    proxy.sig2 = new Signature(name2, desc);
    proxy.createInfo = new CreateInfo(c1, c2);
    return proxy;
  }

方法2:MethodProxy类的invoke方法

MethodProxy

  public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
      //这个过程会创建类型为代理类跟被代理的FastClass类
      init();
      //获取init中封装好的信息
      FastClassInfo fci = fastClassInfo;
      //调用被代理类的方法,传递方法index下标,通过该下标会在FastClass找出对应的方法并执行
      return fci.f2.invoke(fci.i2, obj, args);
    }
    catch (InvocationTargetException ex) {
      throw ex.getTargetException();
    }
    catch (IllegalArgumentException ex) {
      if (fastClassInfo.i1 < 0)
        throw new IllegalArgumentException("Protected method: " + sig1);
      throw ex;
    }
  }

init(),见方法3详解

方法3:MethodProxy类的init方法

  private void init() {
    /*
     * Using a volatile invariant allows us to initialize the FastClass and
     * method index pairs atomically.
     *
     * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this
     * code could allow fastClassInfo to be instantiated more than once, which
     * appears to be benign.
     */
    if (fastClassInfo == null) {
      synchronized (initLock) {
        //判断是否缓存过
        if (fastClassInfo == null) {
          CreateInfo ci = createInfo;
          FastClassInfo fci = new FastClassInfo();
          //生成被代理类的FastClass对象
          fci.f1 = helper(ci, ci.c1);
          //生成代理类的FastClass对象
          fci.f2 = helper(ci, ci.c2);
          //根据sig值计算出该方法名在被代理类FastClass中对应的下标
          fci.i1 = fci.f1.getIndex(sig1);
          //根据sig值计算出该方法名在代理类FastClass中对应的下标
          fci.i2 = fci.f2.getIndex(sig2);
          fastClassInfo = fci;
          createInfo = null;
        }
      }
    }
  }

生成FastClass对象的过程跟生成代理类过程有点类似,这里不做讲解,后面会讲解代理类的创建过程,过程都差不多。

方法4:enhancer.create方法

代理类会在我们测试用例中调用enhancer.create()方法时进行创建。

  public Object create() {
    classOnly = false;
    argumentTypes = null;
    return createHelper();
  }
  private Object createHelper() {
    //校验callbackTypes、filter是否为空,以及为空时的处理
    preValidate();
    //通过newInstance方法来创建EnhancerKey对象.KEY_FACTORY对象在测试用例new Enhance流程中会被动态代理创建
    Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
        ReflectUtils.getNames(interfaces),
        filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
        callbackTypes,
        useFactory,
        interceptDuringConstruction,
        serialVersionUID);
    this.currentKey = key;
    //开始创建
    Object result = super.create(key);
    return result;
  }

super.create(key),见方法5详解

方法5:create

  protected Object create(Object key) {
    try {
      //获取类加载器
      ClassLoader loader = getClassLoader();
      //尝试从缓存中获取当前类加载器对应的ClassLoaderData对象
      Map<ClassLoader, ClassLoaderData> cache = CACHE;
      ClassLoaderData data = cache.get(loader);
      //获取不到则创建
      if (data == null) {
        synchronized (AbstractClassGenerator.class) {
          cache = CACHE;
          data = cache.get(loader);
          if (data == null) {
            //创建ClassLoaderData并加入newCache缓存中
            Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
            data = new ClassLoaderData(loader);
            newCache.put(loader, data);
            CACHE = newCache;
          }
        }
      }
      this.key = key;
      //生成代理对象
      Object obj = data.get(this, getUseCache());
      //如果类似是Class对象,则进行实例化
      if (obj instanceof Class) {
        return firstInstance((Class) obj);
      }
      return nextInstance(obj);
    }
    catch (RuntimeException | Error ex) {
      throw ex;
    }
    catch (Exception ex) {
      throw new CodeGenerationException(ex);
    }
  }

new ClassLoaderData(loader),见方法6详解

data.get(this, getUseCache()),见方法7详解

方法6:new ClassLoaderData(loader)

这个类比较长,这里我就把比较重要的两个方法进行讲解,这里

protected static class ClassLoaderData {
    private final Set<String> reservedClassNames = new HashSet<String>();
    /**
     * {@link AbstractClassGenerator} here holds "cache key" (e.g. {@link org.springframework.cglib.proxy.Enhancer}
     * configuration), and the value is the generated class plus some additional values
     * (see {@link #unwrapCachedValue(Object)}.
     * <p>The generated classes can be reused as long as their classloader is reachable.</p>
     * <p>Note: the only way to access a class is to find it through generatedClasses cache, thus
     * the key should not expire as long as the class itself is alive (its classloader is alive).</p>
     */
    private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
    /**
     * Note: ClassLoaderData object is stored as a value of {@code WeakHashMap<ClassLoader, ...>} thus
     * this classLoader reference should be weak otherwise it would make classLoader strongly reachable
     * and alive forever.
     * Reference queue is not required since the cleanup is handled by {@link WeakHashMap}.
     */
    private final WeakReference<ClassLoader> classLoader;
    private final Predicate uniqueNamePredicate = new Predicate() {
      public boolean evaluate(Object name) {
        return reservedClassNames.contains(name);
      }
    };
    //这里存的是Function函数,后续步骤中会调用
    private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
      public Object apply(AbstractClassGenerator gen) {
        return gen.key;
      }
    };
    public ClassLoaderData(ClassLoader classLoader) {
      if (classLoader == null) {
        throw new IllegalArgumentException("classLoader == null is not yet supported");
      }
      this.classLoader = new WeakReference<ClassLoader>(classLoader);
      //这里创建的是函数式接口,后续步骤中会调用
      Function<AbstractClassGenerator, Object> load =
          new Function<AbstractClassGenerator, Object>() {
            //创建代理类
            public Object apply(AbstractClassGenerator gen) {
              Class klass = gen.generate(ClassLoaderData.this);
              return gen.wrapCachedClass(klass);
            }
          };
      generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
    }
    public ClassLoader getClassLoader() {
      return classLoader.get();
    }
    public void reserveName(String name) {
      reservedClassNames.add(name);
    }
    public Predicate getUniqueNamePredicate() {
      return uniqueNamePredicate;
    }
    public Object get(AbstractClassGenerator gen, boolean useCache) {
      if (!useCache) {
        return gen.generate(ClassLoaderData.this);
      }
      else {
        Object cachedValue = generatedClasses.get(gen);
        return gen.unwrapCachedValue(cachedValue);
      }
    }
  }

方法7:get

    public Object get(AbstractClassGenerator gen, boolean useCache) {
      //如果没有使用缓存,则直接调用创建代理类方法
      if (!useCache) {
        return gen.generate(ClassLoaderData.this);
      }
      else {
        //这里会调用方法6中创建的两个Function函数式类
        Object cachedValue = generatedClasses.get(gen);
        return gen.unwrapCachedValue(cachedValue);
      }
    }
    public Object get(AbstractClassGenerator gen, boolean useCache) {
      //如果没有使用缓存,则直接调用创建代理类方法
      if (!useCache) {
        return gen.generate(ClassLoaderData.this);
      }
      else {
        //这里会调用方法6中创建的两个Function函数式类
        Object cachedValue = generatedClasses.get(gen);
        return gen.unwrapCachedValue(cachedValue);
      }
    }

this.createEntry(key, cacheKey, v),见方法8详解

方法8:createEntry

protected V createEntry(final K key, KK cacheKey, Object v) {
        boolean creator = false;
        FutureTask task;
        Object result;
        if (v != null) {
            task = (FutureTask)v;
        } else {
          //创建线程
            task = new FutureTask(new Callable<V>() {
                public V call() throws Exception {
                  //调用方法6中写好的Function函数
                    return LoadingCache.this.loader.apply(key);
                }
            });
            //将线程加入缓存中
            result = this.map.putIfAbsent(cacheKey, task);
            if (result == null) {
                creator = true;
                 //开启线程
                task.run();
            } else {
                if (!(result instanceof FutureTask)) {
                    return result;
                }
                task = (FutureTask)result;
            }
        }
        try {
            result = task.get();
        } catch (InterruptedException var9) {
            throw new IllegalStateException("Interrupted while loading cache item", var9);
        } catch (ExecutionException var10) {
            Throwable cause = var10.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException)cause;
            }
            throw new IllegalStateException("Unable to load cache item", cause);
        }
        if (creator) {
            this.map.put(cacheKey, result);
        }
        return result;
    }

LoadingCache.this.loader.apply(key),见方法9详解

方法9:apply

调用函数式接口

  public Object apply(AbstractClassGenerator gen) {
    Class klass = gen.generate(ClassLoaderData.this);
    return gen.wrapCachedClass(klass);
  }
  protected Class generate(ClassLoaderData data) {
    validate();
    //设置代理类名称前缀
    if (superclass != null) {
      setNamePrefix(superclass.getName());
    }
    else if (interfaces != null) {
      setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
    }
    return super.generate(data);
  }
  protected Class generate(ClassLoaderData data) {
    Class gen;
    Object save = CURRENT.get();
    //将当前代理类生成器存入线程中
    CURRENT.set(this);
    try {
      //获取类加载器
      ClassLoader classLoader = data.getClassLoader();
      if (classLoader == null) {
        throw new IllegalStateException("ClassLoader is null while trying to define class " +
            getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
            "Please file an issue at cglib's issue tracker.");
      }
      synchronized (classLoader) {
        //生成代理类名称
        String name = generateClassName(data.getUniqueNamePredicate());
        //缓存中存入这个名称
        data.reserveName(name);
        //当前代理类设置了吗
        this.setClassName(name);
      }
      if (attemptLoad) {
        try {
        //尝试使用类加载器获取代理对象,获取到则返回
          gen = classLoader.loadClass(getClassName());
          return gen;
        }
        catch (ClassNotFoundException e) {
          // ignore
        }
      }
      //生成代理类字节码流
      byte[] b = strategy.generate(this);
      //获取字节码代表的代理类名称
      String className = ClassNameReader.getClassName(new ClassReader(b));
      ProtectionDomain protectionDomain = getProtectionDomain();
      synchronized (classLoader) { // just in case
        // SPRING PATCH BEGIN
        gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
        // SPRING PATCH END
      }
      return gen;
    }
    catch (RuntimeException | Error ex) {
      throw ex;
    }
    catch (Exception ex) {
      throw new CodeGenerationException(ex);
    }
    finally {
      CURRENT.set(save);
    }
  }

strategy.generate(this),见方法10详解

方法10:generate

    public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = this.getClassVisitor();
        this.transform(cg).generateClass(cw);
        return this.transform(cw.toByteArray());
    }
  public void generateClass(ClassVisitor v) throws Exception {
    //如果目标类存在则以目标类为父类,否则以Object为父类
    Class sc = (superclass == null) ? Object.class : superclass;
    if (TypeUtils.isFinal(sc.getModifiers()))
      throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
    //获取父类的所有构造函数
    List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
    //去掉private不能被继承的构造函数
    filterConstructors(sc, constructors);
    // Order is very important: must add superclass, then
    // its superclass chain, then each interface and
    // its superinterfaces.
    //存放代理类的所有方法
    List actualMethods = new ArrayList();
    List interfaceMethods = new ArrayList();
    final Set forcePublic = new HashSet();
    //获取其父类的所有方法,包括父类的父类... 父类的所有接口包含的方法,过滤掉不能被继承的方法
    getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
    //所有方法进行修饰符处理
    List methods = CollectionUtils.transform(actualMethods, new Transformer() {
      public Object transform(Object value) {
        Method method = (Method) value;
        int modifiers = Constants.ACC_FINAL
            | (method.getModifiers()
            & ~Constants.ACC_ABSTRACT
            & ~Constants.ACC_NATIVE
            & ~Constants.ACC_SYNCHRONIZED);
        if (forcePublic.contains(MethodWrapper.create(method))) {
          modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
        }
        return ReflectUtils.getMethodInfo(method, modifiers);
      }
    });
    //创建写日期
    ClassEmitter e = new ClassEmitter(v);
    if (currentData == null) {
      e.begin_class(Constants.V1_8,
          Constants.ACC_PUBLIC,
          getClassName(),
          Type.getType(sc),
          (useFactory ?
              TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
              TypeUtils.getTypes(interfaces)),
          Constants.SOURCE_FILE);
    }
    else {
      e.begin_class(Constants.V1_8,
          Constants.ACC_PUBLIC,
          getClassName(),
          null,
          new Type[]{FACTORY},
          Constants.SOURCE_FILE);
    }
    List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
    e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
    e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
    if (!interceptDuringConstruction) {
      e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
    }
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
    if (serialVersionUID != null) {
      e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
    }
    for (int i = 0; i < callbackTypes.length; i++) {
      e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
    }
    // This is declared private to avoid "public field" pollution
    e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
    if (currentData == null) {
      //写入方法
      emitMethods(e, methods, actualMethods);
      //写入构造方法
      emitConstructors(e, constructorInfo);
    }
    else {
      emitDefaultConstructor(e);
    }
    //写入回调方法
    emitSetThreadCallbacks(e);
    //写入静态代理块
    emitSetStaticCallbacks(e);
    //绑定回调方法
    emitBindCallbacks(e);
    if (useFactory || currentData != null) {
      int[] keys = getCallbackKeys();
      emitNewInstanceCallbacks(e);
      emitNewInstanceCallback(e);
      emitNewInstanceMultiarg(e, constructorInfo);
      emitGetCallback(e, keys);
      emitSetCallback(e, keys);
      emitGetCallbacks(e);
      emitSetCallbacks(e);
    }
    e.end_class();
  }

到这里整个代理类创建过程就差不多告一段落了。

总结

Cglib动态代理不需要被代理类实现接口,根据原理我们知道生成的代理类是继承了被代理类,而且其方法调用方法是使用FastClass,这与JDK动态代理的反射有比较大的区别。


JDK和CGLIB动态代理的区别:


JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。


CGLIB代理使用字节码处理框架ASM,对代理对象类的class文件加载进来,通过修改字节码生成子类。


JDK创建代理对象效率较高,执行效率较低;


CGLIB创建代理对象效率较低,执行效率高。


JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;


CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不- 能代理final修饰的类。


JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:


1.实现InvocationHandler接口,重写invoke()

2.使用Proxy.newProxyInstance()产生代理对象

3.被代理的对象必须要实现接口

CGLib 必须依赖于CGLib的类库,需要满足以下要求:


1.实现MethodInterceptor接口,重写intercept()

2.使用Enhancer对象.create()产生代理对象



目录
相关文章
|
Java Maven
JDK动态代理和CGLIB动态代理的区别及实例
JDK动态代理和CGLIB动态代理的区别及实例
197 0
|
11月前
|
缓存 Java
分析cglib动态代理的实现(上)
分析cglib动态代理的实现(上)
61 0
|
11月前
|
Java
分析cglib动态代理的实现(下)
分析cglib动态代理的实现(下)
46 0
|
Java 索引 Spring
静态代理?动态代理?JDK动态代理和CGLIB包实现动态代理的区别
什么是静态代理?什么是动态代理?JDK动态代理和CGLIB包实现动态代理的区别
118 1
静态代理?动态代理?JDK动态代理和CGLIB包实现动态代理的区别
|
缓存 Java 测试技术
动态代理:JDK动态代理源码学习
动态代理:JDK动态代理源码学习
62 1
|
Java Spring
jdk动态代理和cglib动态代理
只有聪明人才能看见的简介~( ̄▽ ̄~)~
85 0
jdk动态代理和cglib动态代理
|
设计模式 Java 数据安全/隐私保护
剖析代理模式及Java两种动态代理(JDK动态代理和CGLIB动态代理)
本文详述了代理模式以及我们经常接触到的两种具体实现(JDK动态代理和CGLIB动态代理),为读者理解代理模式、JDK动态代理和CGLIB动态代理提供帮助
193 0
剖析代理模式及Java两种动态代理(JDK动态代理和CGLIB动态代理)
|
Java Spring
动态代理学习(二)JDK动态代理源码分析
动态代理学习(二)JDK动态代理源码分析
81 0
动态代理学习(二)JDK动态代理源码分析
|
Java 索引
jdk动态代理和cglib动态代理的原理分析(下)
jdk动态代理和cglib动态代理的原理分析(下)
222 0
jdk动态代理和cglib动态代理的原理分析(下)
|
设计模式 Java 索引
jdk动态代理和cglib动态代理的原理分析(上)
jdk动态代理和cglib动态代理的原理分析(上)
jdk动态代理和cglib动态代理的原理分析(上)