【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】

1. 图解

【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第1张图片

上图主要描述了Cglib动态代理的主要执行过程,下面做详细分析,以下源码使用的Cglib版本为3.2.12。

2. Enhancer源码分析

public Object create() {
    // 判断是否需要创建对象,false表示需要创建对象
    classOnly = false;
    // 使用的是无参构造函数,参数为null
    argumentTypes = null;
    // 创建动态代理class的方法
    return createHelper();
}

...//此处省略

private Object createHelper() {
    // 检查CallBack的类型是否符合要求
    preValidate();
    // 创建唯一标识
    Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
            ReflectUtils.getNames(interfaces),
            filter == ALL_ZERO ? null : new WeakCacheKey(filter),
            callbackTypes,
            useFactory,
            interceptDuringConstruction,
            serialVersionUID);
    this.currentKey = key;
    // 调用父类创建对象
    Object result = super.create(key);
    return result;
}

使用唯一标识key,用来创建生成唯一的动态代理类,然后将创建的工作委托给父类进行,下面分析父类AbstractClassGenerator的create方法。

3. AbstractClassGenerator源码分析

   protected Object create(Object key) {
        try {
            // 获取类加载器
            ClassLoader loader = getClassLoader();
            // 应用缓存,其中key为类加载器,value通过该classloader加载的动态代理类
            Map cache = CACHE;
            ClassLoaderData data = cache.get(loader);
            if (data == null) {
                synchronized (AbstractClassGenerator.class) {
                    cache = CACHE;
                    data = cache.get(loader);
                    if (data == null) {
                        Map newCache = new WeakHashMap(cache);
                        data = new ClassLoaderData(loader);
                        newCache.put(loader, data);
                        CACHE = newCache;
                    }
                }
            }
            this.key = key;
            // 获取缓存对象
            Object obj = data.get(this, getUseCache());
            // 如果返回的是Class对象,则创建一个该Class类的实例
            if (obj instanceof Class) {
                return firstInstance((Class) obj);
            }
            // 如果从缓存获取的是EnhancerFactoryData对象,那么说明已经存在一个相应的动态代理Class对象
            return nextInstance(obj);
        } catch (RuntimeException e) {
            throw e;
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

下面进入data.get()

public Object get(AbstractClassGenerator gen, boolean useCache) {
    // 如果useCache为false,表示未使用缓存
    if (!useCache) {
      // 传入ClassLoaderData这个内部类的当前对象
      return gen.generate(ClassLoaderData.this);
    } else {
      // 如果useCache为true,表示使用缓存
      Object cachedValue = generatedClasses.get(gen);
      return gen.unwrapCachedValue(cachedValue);
    }
}

从源码可以看出,若未使用缓存,则调用gen.generate方法,若使用缓存调用generatedClasses.get。下面会依次分析,先分析gen.generate

    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
                if (protectionDomain == null) {
                    gen = ReflectUtils.defineClass(className, b, classLoader);
                } else {
                    // 通过classloader加载类字节码,返回一个Class对象
                    gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
                }
            }
            // 返回生成的Class对象
            return gen;
        } catch (RuntimeException e) {
            throw e;
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        } finally {
            CURRENT.set(save);
        }
    }

上面代码中有个核心方法,strategy.generate,默认会进入DefaultGeneratorStrategy的generate方法

    public byte[] generate(ClassGenerator cg) throws Exception {
        // 获取ClassWriter
        DebuggingClassWriter cw = getClassVisitor();
        // 通过ClassWriter,生成一个代理类的Class文件
        transform(cg).generateClass(cw);
        // 将代理类的Class文件转换成字节数组
        return transform(cw.toByteArray());
    }

上述代码中,generateClass方法生成Class文件是底层核心实现,通过ASM框架,完成类的Class对象的组装,默认走KeyFactory类的generateClass。

      public void generateClass(ClassVisitor v) {
            ClassEmitter ce = new ClassEmitter(v);
            
            Method newInstance = ReflectUtils.findNewInstance(keyInterface);
            if (!newInstance.getReturnType().equals(Object.class)) {
                throw new IllegalArgumentException("newInstance method must return Object");
            }

            Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
            // 开始生成类的基本信息,包含Class版本号、访问权限、Class名字等
            ce.begin_class(Constants.V1_2,
                           Constants.ACC_PUBLIC,
                           getClassName(),
                           KEY_FACTORY,
                           new Type[]{ Type.getType(keyInterface) },
                           Constants.SOURCE_FILE);
            EmitUtils.null_constructor(ce);
            EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));

            int seed = 0;
            // 生成代理类的方法
            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
                                            TypeUtils.parseConstructor(parameterTypes),
                                            null);
            e.load_this();
            e.super_invoke_constructor();
            e.load_this();
            List fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class);
            for (int i = 0; i < parameterTypes.length; i++) {
                Type parameterType = parameterTypes[i];
                Type fieldType = parameterType;
                for (FieldTypeCustomizer customizer : fieldTypeCustomizers) {
                    fieldType = customizer.getOutType(i, fieldType);
                }
                seed += fieldType.hashCode();
                ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
                                 getFieldName(i),
                                 fieldType,
                                 null);
                e.dup();
                e.load_arg(i);
                for (FieldTypeCustomizer customizer : fieldTypeCustomizers) {
                    customizer.customize(e, i, parameterType);
                }
                e.putfield(getFieldName(i));
            }
            e.return_value();
            e.end_method();
            
            // 生成代理类的hashcode方法
            e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
            int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)];
            int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)];
            e.push(hc);
            for (int i = 0; i < parameterTypes.length; i++) {
                e.load_this();
                e.getfield(getFieldName(i));
                EmitUtils.hash_code(e, parameterTypes[i], hm, customizers);
            }
            e.return_value();
            e.end_method();

            // 生成代理类的equals方法
            e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
            Label fail = e.make_label();
            e.load_arg(0);
            e.instance_of_this();
            e.if_jump(e.EQ, fail);
            for (int i = 0; i < parameterTypes.length; i++) {
                e.load_this();
                e.getfield(getFieldName(i));
                e.load_arg(0);
                e.checkcast_this();
                e.getfield(getFieldName(i));
                EmitUtils.not_equals(e, parameterTypes[i], fail, customizers);
            }
            e.push(1);
            e.return_value();
            e.mark(fail);
            e.push(0);
            e.return_value();
            e.end_method();

            // 生成代理类的toString方法
            e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
            e.new_instance(Constants.TYPE_STRING_BUFFER);
            e.dup();
            e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
            for (int i = 0; i < parameterTypes.length; i++) {
                if (i > 0) {
                    e.push(", ");
                    e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
                }
                e.load_this();
                e.getfield(getFieldName(i));
                EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizers);
            }
            e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
            e.return_value();
            e.end_method();
            // 生成代理类结束
            ce.end_class();
      }

通过分析上述代码,得知代理类的Class字节码文件生成是由底层的ClassEmitter封装ASM框架完成的,关于ASM框架,将在下一讲继续深入,里面涉及到三种设计模式的具体应用。
如果使用缓存方式获取代理类的Class对象,会调用generatedClasses.get,进入方法会到LoadingCache中

    public V get(K key) {
        final KK cacheKey = keyMapper.apply(key);
        Object v = map.get(cacheKey);
        if (v != null && !(v instanceof FutureTask)) {
            return (V) v;
        }

        return createEntry(key, cacheKey, v);
    }

进入createEntry

 protected V createEntry(final K key, KK cacheKey, Object v) {
        FutureTask task;
        boolean creator = false;
        if (v != null) {
            // Another thread is already loading an instance
            task = (FutureTask) v;
        } else {
            task = new FutureTask(new Callable() {
                public V call() throws Exception {
                    return loader.apply(key);
                }
            });
            Object prevTask = map.putIfAbsent(cacheKey, task);
            if (prevTask == null) {
                // creator does the load
                creator = true;
                task.run();
            } else if (prevTask instanceof FutureTask) {
                task = (FutureTask) prevTask;
            } else {
                return (V) prevTask;
            }
        }

上面代码会调用task.run,进入线程loader.apply方法,最终进入AbstractClassGenerator的内部类ClassLoaderData的方法

       public ClassLoaderData(ClassLoader classLoader) {
            if (classLoader == null) {
                throw new IllegalArgumentException("classLoader == null is not yet supported");
            }
            this.classLoader = new WeakReference(classLoader);
            Function load =
                    new Function() {
                        public Object apply(AbstractClassGenerator gen) {
                            Class klass = gen.generate(ClassLoaderData.this);
                            return gen.wrapCachedClass(klass);
                        }
                    };
            generatedClasses = new LoadingCache(GET_KEY, load);
        }

会发现,匿名内部类里面还是会调用上面代码分析过的gen.generate方法,最终通过字节码框架ASM生成Class对象。

3. 逐步调试解析

整个调试过程从【趣味设计模式系列】之【代理模式1-基本原理、实战及框架应用】中的CglibTest示例程序开始调试,下面调试过程会比较长,总共分三个阶段。

3.1 初始化Enhancer实例阶段

【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第2张图片
进入CglibProxy的createProxy方法,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第3张图片
当执行到13行时,会初始化父类AbstractClassGenerator的静态常量值DEFAULT_USE_CACHE,该值默认为true,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第4张图片
接着会初始化Enhancer的静态常量KEY_FACTORY,该值也是创建EnhancerKey对象的关键,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第5张图片
随后进入KeyFactory的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第6张图片
上述方法里面会调用gen.create
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第7张图片
继续调用静态内部类Generator的create方法,接口名为interface net.sf.cglib.proxy.Enhancer$EnhancerKey
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第8张图片
随后调用super.create,进入父类AbstractClassGenerator的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第9张图片
再往下会优先从缓存取数据
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第10张图片
进入data.get方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第11张图片
默认useCache为true,会走else逻辑,随后会进入LoadingCache的get方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第12张图片
上面代码34行,会执行createEntry,进入LoadingCache类52行的task线程中,61行线程执行run方法,会执行线程内部call的方法,调用loader.apply
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第13张图片
再往下会走到AbstractClassGenerator的96行
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第14张图片
进入generate方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第15张图片
再走到320行,进入generateClassName方法,执行生成类名的方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第16张图片
随后又回到AbstractClassGenerator,执行332行
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第17张图片
进入默认字节码生成策略类DefaultGeneratorStrategy的generate方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第18张图片
执行到25行,进入KeyFactory类的generatorClass方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第19张图片
上述代码,从241行开始,通过ASM框架生成新的类
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第20张图片
通过观察类名,ce下面的classinfo信息,看出生成类名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72的类,
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第21张图片
最后又回到AbstractClassGenerator类的296行,用生成的Class对象,通过反射生成上述类名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
实例
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第22张图片

以上步骤都是在执行Enhancer enhancer = new Enhancer()这一步完成的,总结上述步骤,就是为创建的代理类生成一个唯一的key,该key又由KeyFactory生成,最终生成的key是类名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72的类。

3.2 代理类生成阶段

下面继续调式,走到CglibProxy的18行,开始执行enhancer.create方法,真正创建代理类,见下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第23张图片
进入Enhancer的create方法,执行到305行
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第24张图片
再进入createHelper方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第25张图片
发现key为之前生成的类名为net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72的实例,属性里面包含若干属性对象,其中FIELD_0为com.wzj.cglib.Apple,FIELD_3为回调类型数组,数组里只有一个元素,值为Lnet/sf/cglib/proxy/MethodInterceptor,再往下继续走,480行会调用父类的create方法,进入又回到之前AbstractClassGenerator类的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第26张图片
执行到294行,从缓存获取值
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第27张图片
进入get方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第28张图片
继续走else逻辑,再进入get方法,走入34行的createEntry方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第29张图片
一直往下走,发现调试步骤与上述一致,中间省去部分步骤,走到代理类的默认命名策略,名字为com.wzj.cglib.Apple$$EnhancerByCGLIB$$3a0529f7
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第30张图片
随后往下几步与上述一致,最终在生成类的Class文件时,与上述稍有不同,会走到Enhancer类的generateClass方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第31张图片
继续往下走,569行有几句注释,执行顺序非常重要,必须先添加父类,以及它的父类链,然后每个接口以及父类接口,随后按照注释说明,到575行,执行getMethods方法,见下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第32张图片
进入getMethods方法,执行到551行,进入MethodWrapper.createSet方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第33张图片
首先会进入静态常量方法包装类的key对应类MethodWrapperKey的实例初始化,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第34张图片
随后进入KeyFactory的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第35张图片
往下221行,执行super.create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第36张图片
进入该方法,又会回到最初的AbstractClassGenerator的create方法,
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第37张图片
再往下与上面调试过的过程类似,中间部分调试省略,最后生成代理类Class文件,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第38张图片
最后回到AbstractClassGenerator类的298行,nextInstance生成代理类的实例
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第39张图片
最终通过设置回调函数,并通过反射完成代理类的实例的初始化,如下图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第40张图片

3.3 代理类的方法执行阶段

【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第41张图片
进入自定义的intercept方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第42张图片
进入invokeSuper方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第43张图片
执行到init方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第44张图片
进入init的74行
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第45张图片
进入helper方法,执行121的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第46张图片
进入create方法,回到AbstractClassGenerator的create方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第47张图片
根据ci得到该方法的被代理类,代理类,分别生成FastClass的两个实例f1,f2,下图是f1的生成过程
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第48张图片
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第49张图片
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第50张图片
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第51张图片
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第52张图片
同理,生成FastClass的实例f2
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第53张图片
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第54张图片
目的是计算被代理类与代理类各自的方法的索引,获取当前方法在f1,f2中的签名,得到一个index,可以根据index映射对应类的对应方法,因此方法名->签名->索引值,三者是一一对应关系。
init方法完成后,往下走到228行,这里通过调用代理类的索引值19对应的方法,取代反射
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第55张图片

进入会走到被代理类的目标方法
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第56张图片

至此,上面代理的全过程已经分析完毕。

4. FastClass源码解析

上述调试过程中,生成了两个FastClass的实例,分别是被代理类与代理类的在执行代理方法时创建,这里应用了一个懒加载的思想,也就是说,一开始并没有FastClass,只有当MethodProxy方法代理真正被请求的时候,被代理类的方法需要映射到代理类的方法时,为了避免过度使用反射,才生成了FastClass的实例,完成调用。
FastClass有两个主要方法,获取方法签名后的索引值,以及根据索引值调用方法,主要思想就是在为了避免方法调用时,过度使用反射造成调用慢的问题,下面是两个方法。

//方法签名后的索引值
abstract public int getIndex(Signature sig);

//根据索引值调用方法
abstract public Object invoke(int index, Object obj, Object[] args) 

示例程序跑完后会在项目的根目录下生成三个类,其中两个FastClass类,一个代理类,如图
【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】_第57张图片

Apple$$FastClassByCGLIB$$ca2d2eb9类是为了使用被代理类的方法索引而生成的

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.wzj.cglib;

import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.reflect.FastClass;

public class Apple$$FastClassByCGLIB$$ca2d2eb9 extends FastClass {
    public Apple$$FastClassByCGLIB$$ca2d2eb9(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1596601914:
            // 当方法为secKill时,索引为0
            if (var10000.equals("secKill()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 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 1969019727:
            if (var1.equals("secKill")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
        }

        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 {
        Apple var10000 = (Apple)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.secKill();
                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 {
        Apple var10000 = new Apple;
        Apple var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

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

    public int getMaxIndex() {
        return 3;
    }
}

Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818类是为了使用代理类的方法索引而生成的,见下图

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.wzj.cglib;

import com.wzj.cglib.Apple..EnhancerByCGLIB..3a0529f7;
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.reflect.FastClass;

public class Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818 extends FastClass {
    public Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -2055565910:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 17;
            }
            break;
        case -1882565338:
            if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
                return 9;
            }
            break;
        case -1596601914:
            if (var10000.equals("secKill()V")) {
                return 7;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 14;
            }
            break;
        case -1411842725:
            if (var10000.equals("CGLIB$hashCode$3()I")) {
                return 8;
            }
            break;
        case -894172689:
            if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case -623122092:
            if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
                return 20;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return 3;
            }
            break;
        case -419626537:
            if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 15;
            }
            break;
        case -266769987:
            if (var10000.equals("CGLIB$secKill$0()V")) {
                return 12;
            }
            break;
        case 560567118:
            if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
                return 13;
            }
            break;
        case 811063227:
            if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 5;
            }
            break;
        case 973717575:
            if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
                return 18;
            }
            break;
        case 1221173700:
            if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case 1230699260:
            if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
                return 19;
            }
            break;
        case 1306468936:
            if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
                return 11;
            }
            break;
        case 1584330438:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 16;
            }
            break;
        case 1800494055:
            if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
                return 10;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 0;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 1;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 2;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 0;
                    }
                }
            }
            break;
        case -1053468136:
            if (var1.equals("getCallbacks")) {
                switch(var2.length) {
                case 0:
                    return 18;
                }
            }
            break;
        case -124978609:
            if (var1.equals("CGLIB$equals$1")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 9;
                    }
                }
            }
            break;
        case -60403779:
            if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 16;
                    }
                }
            }
            break;
        case -29025555:
            if (var1.equals("CGLIB$hashCode$3")) {
                switch(var2.length) {
                case 0:
                    return 8;
                }
            }
            break;
        case 85179481:
            if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 17;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 2;
                }
            }
            break;
        case 161998109:
            if (var1.equals("CGLIB$STATICHOOK1")) {
                switch(var2.length) {
                case 0:
                    return 14;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 15;
                    }
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {
                        return 20;
                    }
                }
            }
            break;
        case 1543336189:
            if (var1.equals("CGLIB$toString$2")) {
                switch(var2.length) {
                case 0:
                    return 11;
                }
            }
            break;
        case 1811874389:
            if (var1.equals("newInstance")) {
                switch(var2.length) {
                case 1:
                    String var10001 = var2[0].getName();
                    switch(var10001.hashCode()) {
                    case -845341380:
                        if (var10001.equals("net.sf.cglib.proxy.Callback")) {
                            return 6;
                        }
                        break;
                    case 1730110032:
                        if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {
                            return 4;
                        }
                    }
                case 2:
                default:
                    break;
                case 3:
                    if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 5;
                    }
                }
            }
            break;
        case 1817099975:
            if (var1.equals("setCallback")) {
                switch(var2.length) {
                case 2:
                    if (var2[0].getName().equals("int") && var2[1].getName().equals("net.sf.cglib.proxy.Callback")) {
                        return 13;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 19;
                    }
                }
            }
            break;
        case 1951977610:
            if (var1.equals("CGLIB$clone$4")) {
                switch(var2.length) {
                case 0:
                    return 10;
                }
            }
            break;
        case 1969019727:
            if (var1.equals("secKill")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            break;
        case 2019235512:
            // 调用CGLIB$secKill$0()时,返回索引值12
            if (var1.equals("CGLIB$secKill$0")) {
                switch(var2.length) {
                case 0:
                    return 12;
                }
            }
        }

        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 {
        3a0529f7 var10000 = (3a0529f7)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.clone();
            case 4:
                return var10000.newInstance((Callback[])var3[0]);
            case 5:
                return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
            case 6:
                return var10000.newInstance((Callback)var3[0]);
            case 7:
                var10000.secKill();
                return null;
            case 8:
                return new Integer(var10000.CGLIB$hashCode$3());
            case 9:
                return new Boolean(var10000.CGLIB$equals$1(var3[0]));
            case 10:
                return var10000.CGLIB$clone$4();
            case 11:
                return var10000.CGLIB$toString$2();
            // 当计算index为12时,调用var10000.CGLIB$secKill$0()
            case 12:
                var10000.CGLIB$secKill$0();
                return null;
            case 13:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 14:
                3a0529f7.CGLIB$STATICHOOK1();
                return null;
            case 15:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 16:
                3a0529f7.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 17:
                3a0529f7.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 18:
                return var10000.getCallbacks();
            case 19:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 20:
                return 3a0529f7.CGLIB$findMethodProxy((Signature)var3[0]);
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

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

    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        3a0529f7 var10000 = new 3a0529f7;
        3a0529f7 var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

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

    public int getMaxIndex() {
        return 20;
    }
}

代理类为Apple$$EnhancerByCGLIB$$3a0529f7,如下图,当下面的CGLIB$secKill$0方法被调用时,父类的super.secKill被执行

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.wzj.cglib;

import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class Apple$$EnhancerByCGLIB$$3a0529f7 extends Apple 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$secKill$0$Method;
    private static final MethodProxy CGLIB$secKill$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("com.wzj.cglib.Apple$$EnhancerByCGLIB$$3a0529f7");
        Class var1;
        CGLIB$secKill$0$Method = ReflectUtils.findMethods(new String[]{"secKill", "()V"}, (var1 = Class.forName("com.wzj.cglib.Apple")).getDeclaredMethods())[0];
        CGLIB$secKill$0$Proxy = MethodProxy.create(var1, var0, "()V", "secKill", "CGLIB$secKill$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");
    }

    // 当CGLIB$secKill$0被执行,调用父类被代理的方法
    final void CGLIB$secKill$0() {
        super.secKill();
    }
    
    // 当代理方法被执行,内部调用自定义intercept方法
    public final void secKill() {
        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$secKill$0$Method, CGLIB$emptyArgs, CGLIB$secKill$0$Proxy);
        } else {
            super.secKill();
        }
    }

    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 -1596601914:
            if (var10000.equals("secKill()V")) {
                return CGLIB$secKill$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$4$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 Apple$$EnhancerByCGLIB$$3a0529f7() {
        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) {
        Apple$$EnhancerByCGLIB$$3a0529f7 var1 = (Apple$$EnhancerByCGLIB$$3a0529f7)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);
        Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7;
        switch(var1.length) {
        case 0:
            var10000.();
            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();
    }
}

5. 总结

5.1 代理的执行的三个阶段

  • 第一阶段,生成唯一代理类需要唯一的key,key的生成又需要KeyFactory,第一阶段就是初始化KeyFactory与key;
  • 第二阶段,生成代理类,代理类中的方法通过方法代理一并生成,其中关键的步骤都是在AbstractClassGenerator中完成的,并在生成过程中默认使用缓存取代理,缓存没有,利用ASM框架生成;
  • 第三阶段,代理方法执行阶段,通过FastClass生成中间类,为目标方法的执行提供方便。

5.2 FastClass机制

  • 使用了懒加载思想,在执行代理方法阶段生成,而非一开始就生成;
  • 通过方法->签名->索引值的映射,直接根据最终的索引值调用代理类方法,而非通过反射,提高效率。

你可能感兴趣的:(【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】)