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

1  前言

上节我们看了 EnhancerKey 是通过KeyFactory里的  Generator来创建代理对象,这节我们就来看下 Enhancer是如何创建代理对象的。

2  源码分析

上节我们看过了,AbstractClassGenerator 是模板模式的枢纽,创建代理对象子类复写 generateClass 和 firstInstance两个方法即可。那么我们就来看下 Enhancer 里的是如何实现的。

2.1  generateClass 

public void generateClass(ClassVisitor v) throws Exception {
    // 就是我们的被代理类  Demo.class
    Class sc = (superclass == null) ? Object.class : superclass;
    // 看见没如果是final直接报错
    if (TypeUtils.isFinal(sc.getModifiers()))
        throw new IllegalArgumentException("Cannot subclass final class " + sc);
    // 构造器并过滤
    List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
    filterConstructors(sc, constructors);
    // 收集方法
    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 对asm的classAdapter和MethodAdapter的实现,贯穿于cglib代码的处理
    // 理解成就是描述类的
    ClassEmitter e = new ClassEmitter(v);
    e.begin_class(Constants.V1_2,
                  Constants.ACC_PUBLIC,
                  getClassName(),
                  Type.getType(sc),
                  (useFactory ?
                   TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
                   TypeUtils.getTypes(interfaces)),
                  Constants.SOURCE_FILE);
    List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
    // 声明属性
    e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_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);
    }
    // 添加方法、构造器、等方法
    emitMethods(e, methods, actualMethods);
    emitConstructors(e, constructorInfo);
    emitSetThreadCallbacks(e);
    emitSetStaticCallbacks(e);
    emitBindCallbacks(e);
    // 这个就是你的代理要不要继承 Factory 可以更改你的增强逻辑
    if (useFactory) {
        int[] keys = getCallbackKeys();
        emitNewInstanceCallbacks(e);
        emitNewInstanceCallback(e);
        emitNewInstanceMultiarg(e, constructorInfo);
        emitGetCallback(e, keys);
        emitSetCallback(e, keys);
        emitGetCallbacks(e);
        emitSetCallbacks(e);
    }
    e.end_class();
}

上边在构造类的属性呀,方法什么的,其中一点我简单说下,有个 useFactory 不知道你发现没,默认是开启的,也就是开启的情况下我们的代理类会实现 Factory接口,那么这个接口是干啥的呢,我们来看下:

主要分三类方法,一类是获取设置的回调,也就是我们的增强的代码类,一类是创建代理对象,一类就是设置增强代码类,也就是说可以更改我们代理类的增强逻辑,我们来试下:

2.2  firstInstance

这个方法 firstInstance ,我们的增强逻辑也是在这个方法里塞进去的,我们来看下具体过程:

protected Object firstInstance(Class type) throws Exception {
    if (classOnly) {
        return type;
    } else {
// 进入这个方法
return createUsingReflection(type); } }
private Object createUsingReflection(Class type) {
    /**
     * type 是什么也就是我们代理类的类信息
     * 将我们的增强类设置进去
     * 然后创建出来代理对象后
     * 发现finally会清空掉类信息里的增强类 至于为什么 可能是保持类的干净?我猜的哈 有知道的可以告知下
     */
    setThreadCallbacks(type, callbacks);
    try{
    // 创建代理对象
    if (argumentTypes != null) {
        return ReflectUtils.newInstance(type, argumentTypes, arguments);
    } else {
        return ReflectUtils.newInstance(type);
    }
    }finally{
        // clear thread callbacks to allow them to be gc'd 清空
        setThreadCallbacks(type, null);
    }
}

ReflectUtils.newInstance 就是获取构造方法创建对象,这里就不看了哈。

整体跟 JDK 创建步骤差不多,大致也分三步:

3  小结

好这节我们大概看了下  Enhancer 对象创建代理对象的过程,主要就是 generateClass 和 firstInstance两个方法,有理解不对的地方欢迎指正哈。

posted @ 2023-03-04 14:08  酷酷-  阅读(71)  评论(0编辑  收藏  举报