【代理】【四】代理源码解析-Cglib代理-Generator代理对象创建过程

1  前言

 上节我们简单感受了下Cglib的一个代理过程,并且我也说到了Enhancer 创建代理的时候,首先会创建对象Key出来,用于标识这个类以及将其作为缓存的Key,然后再创建代理对象并放进缓存,那么这节我们就来看下执行的一个具体过程。

2  源码分析

2.1  Key创建的时机

首先我们先来看下是什么时候需要创建Key的,

// EnhancerKey
public Object create() {
    classOnly = false;
    argumentTypes = null;
    return createHelper();
}
// Key对象
private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class);
private Object createHelper() {
    validate();
    if (superclass != null) {
        setNamePrefix(superclass.getName());
    } else if (interfaces != null) {
        setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
    }
    // 这里就需要先创建被代理对象的 Key 出来,再调用父类进行代理对象的创建
    return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
                                                ReflectUtils.getNames(interfaces),
                                                filter,
                                                callbackTypes,
                                                useFactory,
                                                interceptDuringConstruction,
                                                serialVersionUID));
}

看这行代码  private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class);可以看到我们的 Key 对象(即 EnhancerKey)是需要借助 KeyFactory 来进行创建的,我们看下:

// KeyFactory
public static KeyFactory create(Class keyInterface) {
    // 调用重载方法
    return create(keyInterface, null);
}
public static KeyFactory create(Class keyInterface, Customizer customizer) {
    // 继续调用重载方法
    return create(keyInterface.getClassLoader(), keyInterface,  customizer);
}
// 通过 Generator 进行创建
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
    Generator gen = new Generator();
    // 设置接口 其实就是 EnhancerKey.class
    gen.setInterface(keyInterface);
    // customizer为null
    gen.setCustomizer(customizer);
    // 即 keyInterface.getClassLoader()
    gen.setClassLoader(loader);
    // 创建
    return gen.create();
}
public static class Generator extends AbstractClassGenerator {
    public KeyFactory create() {
      setNamePrefix(keyInterface.getName());
     // super.create 返回的是 Object 为什么能强转为 KeyFactory?   
return (KeyFactory)super.create(keyInterface.getName()); } }

我看完有两个疑问:

  • Generator 的 create 方法返回的是 Object对象为什么能强转为 KeyFactory ?
  • KeyFactory 为什么又能强转为 EnhancerKey  ?

那么我们带着这样的疑问来看下具体的创建过程是怎么样的。

2.2  创建过程

2.2.1  KeyFactory - create

我们就从这里开始,我们的 EnhancerKey 是由 KeyFactory 里的 Generator 来创建的:

// 通过 Generator 进行创建 keyInterface 即 EnhancerKey.class
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
    Generator gen = new Generator();
    // 设置接口 其实就是 EnhancerKey.class
    gen.setInterface(keyInterface);
    // customizer为null
    gen.setCustomizer(customizer);
    // 即 keyInterface.getClassLoader()
    gen.setClassLoader(loader);
    // 创建
    return gen.create();
}

2.2.2 Generator - create 创建代理

那我们进入 Generator 看一下里边是如何创建的:

public static class Generator extends AbstractClassGenerator {
    // 缓存
    private static final Source SOURCE = new Source(KeyFactory.class.getName());
    // 接口
    private Class keyInterface;
    // 个性化
    private Customizer customizer;
    private int constant;
    private int multiplier;
    public Generator() {
        super(SOURCE);
    }
    public KeyFactory create() {
        // 设置名称前缀
        setNamePrefix(keyInterface.getName());
        // 调用父类创建代理对象
        return (KeyFactory)super.create(keyInterface.getName());
    }
}

我们首先看下 Generator 的初始化方法,是调用父类的,那么我们看一下父类即就是我们的 AbstractClassGenerator 的初始化:

abstract public class AbstractClassGenerator
implements ClassGenerator
{
    private static final Object NAME_KEY = new Object();
    
    private Source source;
    // Source内部类 缓存
    protected static class Source {
        String name;
        // 缓存
        Map cache = new WeakHashMap();
        public Source(String name) {
            this.name = name;
        }
    }
    // 初始化缓存
    protected AbstractClassGenerator(Source source) {
        this.source = source;
    }
}

2.2.3 AbstractClassGenerator - create 创建代理

看见初始化就是初始化缓存变量的值,那么我们继续看 Generator 的 create 方法,也是调用父类 AbstractClassGenerator 的create方法,我们来看下具体的源码:

protected Object create(Object key) {
    try {
        Class gen = null;
        synchronized (source) {
            // 获取类加载器
            ClassLoader loader = getClassLoader();
            Map cache2 = null;
            // 先判断缓存中有没有
            cache2 = (Map)source.cache.get(loader);
            /**
             * 缓存为空说明不存在,初始化缓存
             * 这里注意一点 cache2 = new HashMap();
             * cache2.put(NAME_KEY, new HashSet()) 往 hashMap中放入 NAME_KEY -> newHashSet()
             * source.cache.put(loader, cache2); 往缓存中放入 loader -> cache2
             * 那么我们的缓存结构就是 <loader, <NAME_KEY, newHashSet()>> 嵌套型的
             */
            if (cache2 == null) {
                cache2 = new HashMap();
                // 初始化 cache2
                cache2.put(NAME_KEY, new HashSet());
                // 初始化缓存
                source.cache.put(loader, cache2);
            } else if (useCache) {
                // 先从缓存中获取
                Reference ref = (Reference)cache2.get(key);
                gen = (Class) (( ref == null ) ? null : ref.get()); 
            }
            // 进行代理对象的创建
            if (gen == null) {
                Object save = CURRENT.get();
                CURRENT.set(this);
                try {
                    this.key = key;
                    // 默认为false 暂时不用管
                    if (attemptLoad) {
                        try {
                            gen = loader.loadClass(getClassName());
                        } catch (ClassNotFoundException e) {
                            // ignore
                        }
                    }
                    /**
                     * 这里就会根据策略进行创建了
                     * strategy 默认的实现为
                     * private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
                     */
                    if (gen == null) {
                        // 创建出代理对象类字节数组
                        byte[] b = strategy.generate(this);
                        /**
                         * 这里的缓存放置的是
                         * <loader,<NAME_KEY, HashSet>>
                         * 这里就是把 className 放进了对应的 HashSet里
                         */
                        String className = ClassNameReader.getClassName(new ClassReader(b));
                        getClassNameCache(loader).add(className);
                        // 生成类的定义文件
                        gen = ReflectUtils.defineClass(className, b, loader);
                    }
                    // 默认开启缓存,如果开启缓存
                    if (useCache) {
                        /**
                         *  放入缓存
                         *  注意上边也放了一次缓存,这里又放了一次 注意两次不一样哈
                         *  这次放的是 key -> WeakReference(gen)
                         *  key 即 EnhancerKey
                         *  val 是 外边包了一层WeakReference的用于创建代理对象的类定义信息,
                         *        也就是下一次如果缓存开启的话直接获取定义信息来创建代理对象即可
                         *  那么我们的source缓存 又呈现<loader,<EnhancerKey, WeakReference(gen)>>
                         */
                        cache2.put(key, new WeakReference(gen));
                    }
                    // 创建代理对象 抽象方法也就是调用子类的方法
                    return firstInstance(gen);
                } finally {
                    CURRENT.set(save);
                }
            }
        }
        return firstInstance(gen);
    } catch (RuntimeException e) {
        throw e;
    } catch (Error e) {
        throw e;
    } catch (Exception e) {
        throw new CodeGenerationException(e);
    }
}

那我们大致总结一下执行过程:

  • 先看缓存中有没有;
  • 没有的话,初始化NAME_KEY缓存;
  • 调用默认策略进行代理对象类字节数组的生成;
  • 调用子类的 firstInstance 创建代理对象。

那么我们再着重看一下默认策略的执行过程:

public class DefaultGeneratorStrategy implements GeneratorStrategy {
    public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
    
    public byte[] generate(ClassGenerator cg) throws Exception {
        ClassWriter cw = getClassWriter();
        // 就是调用子类的 generateClass 方法
        transform(cg).generateClass(cw);
        return transform(cw.toByteArray());
    }

    protected ClassGenerator transform(ClassGenerator cg) throws Exception {
        return cg;
    }
}

发现其就是调用子类的  generateClass 方法。

好了到这里为止,我们可以发现 EnhancerKey 本身是个接口,通过 KeyFactory里的 Generator为其床创建代理对象,创建代理对象的两个步骤就是1、调用子类的 generateClass方法获取到代理对象的类字节信息。2、调用子类的firstInstance 方法创建代理对象的。不知道你晕没晕,那么我们接下里就要看什么了?是不是要看一下 Generator 里的 generateClass 和 firstInstance 方法啦。

2.3  Generator - generateClass 

我们来看下 Generator 的 generateClass 方法:

public void generateClass(ClassVisitor v) {
    // ClassEmitter 对 asm 的classAdapter和MethodAdapter的实现,贯穿于cglib代码的处理
    ClassEmitter ce = new ClassEmitter(v);
    // 找到接口中的方法名字不是newInstance的以及返回值类型不是Object的就报错
    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());
    ce.begin_class(Constants.V1_2,
                   Constants.ACC_PUBLIC,
                   getClassName(),
                   KEY_FACTORY,  // 看这里 KEY_FACTORY 也就是代理类是继承 KeyFactory的
                   new Type[]{ Type.getType(keyInterface) }, // 看这里接口 就是你那个 EnhancerKey
                   Constants.SOURCE_FILE);
    // 空参构造方法
    EmitUtils.null_constructor(ce);
    // 生成newInstance工厂方法
    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();
    // 参数处理
    for (int i = 0; i < parameterTypes.length; i++) {
        seed += parameterTypes[i].hashCode();
        ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
                         getFieldName(i),
                         parameterTypes[i],
                         null);
        e.dup();
        e.load_arg(i);
        e.putfield(getFieldName(i));
    }
    e.return_value();
    e.end_method();
    
    // hash code方法
    ...// equals方法
    ...// toString方法
    ...
    e.return_value();
    e.end_method();
    ce.end_class();
}

到这里我们就恍然大悟了,我们的代理对象创建出来就会继承 KeyFactory,并且实现 EnhancerKey 接口。这就解决了我们上边的两个疑惑哈。

2.4  Generator - firstInstance 

那么我们最后再来看下 firstInstance 的东西:

protected Object firstInstance(Class type) {
    return ReflectUtils.newInstance(type);
}

比较简单了哈,就是反射获取构造器创建代理对象的实例完工。

3  生成的代理对象类信息

那我们看下最后生出来的代理对象类长什么样子,看其实就是属性和两个构造器以及Object中的几个方法(这几个方法就不贴了哈比较多)。

public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72 extends KeyFactory implements EnhancerKey {
    private final String FIELD_0;
    private final String[] FIELD_1;
    private final CallbackFilter FIELD_2;
    private final Type[] FIELD_3;
    private final boolean FIELD_4;
    private final boolean FIELD_5;
    private final Long FIELD_6;
    public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72() {
    }
    public Object newInstance(String var1, String[] var2, CallbackFilter var3, Type[] var4, boolean var5, boolean var6, Long var7) {
        return new Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(var1, var2, var3, var4, var5, var6, var7);
    }
    public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(String var1, String[] var2, CallbackFilter var3, Type[] var4, boolean var5, boolean var6, Long var7) {
        this.FIELD_0 = var1;
        this.FIELD_1 = var2;
        this.FIELD_2 = var3;
        this.FIELD_3 = var4;
        this.FIELD_4 = var5;
        this.FIELD_5 = var6;
        this.FIELD_6 = var7;
    }
... }

4  小结

好了本节我们主要看了一下 EnhancerKey 代理创建的过程,它主要用于 Enhancer 的 key,至于为什么要这么要这么做,还着实有点不太懂为什么哈,希望知道的小伙伴告知下,有理解不对的地方欢迎指正哈。

posted @ 2023-03-03 21:57  酷酷-  阅读(149)  评论(0编辑  收藏  举报