6.CGLIB动态代理源码之Enhancer#create


highlight: arduino-light

Enhancer#create

在我们的测试类中,大家发现了,我们创建了一个Enhancer对象,并且设置了父类、回调函数等参数,最重要的入口函数是create方法。

java /** * 如果必须要创建一个新类,那么就用指定的回调对象创建一个新的对象实例 * 使用的父类的参数的构造方法来实例化父类的部分 */ public Object create() { //不作代理类限制 classOnly = false; //没有构造参数类型 argumentTypes = null; //执行创建 return createHelper(); }

Enhancer#createHelper

java private Object createHelper() { //校验callbackTypes、filter是否为空,以及为空时的处理 preValidate(); //通过EnhancerKey创建key //终于知道为什么叫Enhancerkey并且变量名是KEY_FACTORY。 //原来EnhancerKey是专门用于生成代理类的缓存的key的类。 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); //设置当前enhancer的key标识 this.currentKey = key; //当前类是Enhancer 父类是AbstractClassGenerator //调用父类即AbstractClassGenerator的创建代理类 Object result = super.create(key); return result; }

AbstractClassGenerator#create

和创建EnhancerKey的代理类一样,最后都调用了AbstractClassGenerator#create方法,不同的是AbstractClassGenerator#create方法的入参key的不同。

EnhancerKey是类的全限定名:net.sf.cglib.proxy.Enhancer$EnhancerKey

而Ehancer创建的代理类的key是由EnhancerKey的代理类创建的。

java //通过EnhancerKey创建的key protected Object create(Object key) { try { //获取到当前生成器的类加载器 ClassLoader loader = getClassLoader(); //CACHE= new WeakHashMap<ClassLoader, ClassLoaderData>(); //CACHE是当前类加载器对应的缓存可以理解为一级缓存 //缓存key为类加载器,缓存的value为ClassLoaderData //ClassLoaderData可以理解为二级缓存 Map<ClassLoader, ClassLoaderData> cache = CACHE; //先根据类加载器从一级缓存中获取对应的ClassLoaderData ClassLoaderData data = cache.get(loader); //如果缓存中的data为空 if (data == null) { synchronized (AbstractClassGenerator.class) { cache = CACHE; data = cache.get(loader); //经典的防止并发修改 二次判断 double check if (data == null) { //新建一个缓存Cache 并把原來的缓存加入新建的缓存中 Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache); //新建一个当前加载器对应的ClassLoaderData 并加到缓存中 //ClassLoaderData#ClassLoaderData data = new ClassLoaderData(loader); //放入新缓存 newCache.put(loader, data); //刷新全局缓存 CACHE = newCache; } } } // 使用创建的key this.key = key; //data:ClassLoaderData //this:Enhancer //getUseCache():可以通过Enhancer.setUseCache()设置 //data是AbstractClassGenerator$ClassLoaderData //返回的是生成好的代理类的class信息 Object obj = data.get(this, getUseCache()); //如果为class则实例化class并返回 就是我们需要的代理类 if (obj instanceof Class) { return firstInstance((Class) obj); } //如果不是则说明是实体 则直接执行另一个方法返回实体 return nextInstance(obj); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } }

因为接下来的代码和创建EnhancerKey的代理类的代码都大同小异,所以直接跳过。

不同的地方在于EnhancerKey生成代理类的字节码用的是KeyFactory.Genrator#generateClass(ClassVisitor c)方法。

Enhancer生成代理类的字节码用的是Enhancer#generateClass(ClassVisitor c)方法。

调用generateClass(ClassVisitor c)方法是在DefaultGeneratorStrategy里,直接从这里看。

DefaultGeneratorStrategy#generate

java public byte[] generate(ClassGenerator cg) throws Exception { //创建一个写入器 DebuggingClassWriter cw = getClassVisitor(); //transform是模板方法 //子类可以通过transform方法加入自己的转换逻辑后 //再执行代理类生成器的generateClass方法 transform(cg).generateClass(cw); //将cw写入的东西转换为byte数组返回 return transform(cw.toByteArray()); }

​ 这里面主要是新建一个写入器,然后执行我们代理类生成器的generateClass方法将class信息写入这个ClassWriter 最后将里面的东西转换为byte数组返回,所以又回到了我们的代理类生成器的generateClass方法,这儿进入的是Enhancer的generateClass方法

Enhancer#generatorClass

```java public void generateClass(ClassVisitor v) throws Exception { //需要代理的类或者接口 即 cglib代理.MyCalculator Class sc = (superclass == null) ? Object.class : superclass; //检查 final类无法被继承 if (TypeUtils.isFinal(sc.getModifiers())) throw new IllegalArgumentException ("Cannot subclass final class " + sc.getName()); //找到MyCalculator的所有的构造函数 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();
    //声明所有必须为public的方法集合  这儿主要是代理类接口实现的接口的方法
    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);

    //1.开始创建类  并写入基本信息  如java版本,类修饰符 类名等
    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());
    //2. 声明一个private boolean 类型的属性:CGLIB$BOUND
    e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
    //3. 声明一个public static Object 类型的属性:CGLIB$FACTORY_DATA
    e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 
                                    FACTORY_DATA_FIELD, OBJECT_TYPE, null);
    // 这个默认为true  
    //如果为false则会声明一个private boolean 类型的属性:CGLIB$CONSTRUCTED
    if (!interceptDuringConstruction) {
        e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, 
                                                Type.BOOLEAN_TYPE, null);
    }
    //4. 声明一个public static final 的ThreadLocal:CGLIB$THREAD_CALLBACKS
    e.declare_field(Constants.PRIVATE_FINAL_STATIC, 
                               THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
    //5. 声明一个public static final 的CallBack类型的数组:CGLIB$STATIC_CALLBACKS
    e.declare_field(Constants.PRIVATE_FINAL_STATIC,
                               STATIC_CALLBACKS_FIELD,CALLBACK_ARRAY, null);
    //如果serialVersionUID不为null  
    //则设置一个public static final 的Long类型 
    //serialVersionUID
    if (serialVersionUID != null) {
        e.declare_field(Constants.PRIVATE_FINAL_STATIC, 
              Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
    }

    //遍历CallBackTypes 即我们构建Enhancer是setCallBack的所有类的类型  
    //本案例中是methodInterceptor 并且只传入了一个
    for (int i = 0; i < callbackTypes.length; i++) {
        //6.声明private修饰  我们自定义的CallBack类型的属性:
        //CGLIB$CALLBACK_0 (从0开始编号,)
        e.declare_field(Constants.ACC_PRIVATE, 
                            getCallbackField(i), callbackTypes[i], null);
    }
    //7声明一个private static 的传入的Object类型的属性:CGLIB$CALLBACK_FILTER
    e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, 
                                CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);

    //判断currentData
    if (currentData == null) {
        //8.如果为null则声明所有的代理类方法的变量 
        //以及其具体的重写实现方法,还有static初始化执行代码块
        emitMethods(e, methods, actualMethods);
        //9.声明构造函数
        emitConstructors(e, constructorInfo);
    } else {
        //声明默认构造函数
        emitDefaultConstructor(e);
    }
    //
    emitSetThreadCallbacks(e);
    emitSetStaticCallbacks(e);
    emitBindCallbacks(e);
    //如果currentData不为null
    if (useFactory || currentData != null) {
        //获取到所有CallBack索引数组
        int[] keys = getCallbackKeys();
        //10.声明三个newInstance方法
        //只有一个callback参数
        emitNewInstanceCallbacks(e);
        //参数为callback数组
        emitNewInstanceCallback(e);
        //参数为callback数组 以及附带的一些参数
        emitNewInstanceMultiarg(e, constructorInfo);
        //11.声明getCallBack方法
        emitGetCallback(e, keys);
        //12.声明setCallBack方法
        emitSetCallback(e, keys);
        //12.声明setCallBacks方法
        emitGetCallbacks(e);
        //12.声明setCallBacks方法
        emitSetCallbacks(e);
    }
    //类声明结束
    e.end_class();

```

getMethods主要 是获取代理类的所有方法 和 代理类所实现接口的所有方法 用字节码将 所有的方法写到一个代理的类中,

```java private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) { // ReflectUtils.addAllMethods(superclass, methods); List target = (interfaceMethods != null) ? interfaceMethods : methods; if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i] != Factory.class) { ReflectUtils.addAllMethods(interfaces[i], target); } } } if (interfaceMethods != null) { if (forcePublic != null) { //这里会触发MethodWrapper类的加载,完成对MethodWrapper.MethodWrapperKey的代理 // MethodWrapper.MethodWrapperKey KEYFACTORY =
// (MethodWrapper.MethodWrapperKey)KeyFactory.create(MethodWrapper.MethodWrapperKey.class); //使用MethodWrapper对所有接口方法创建唯一标识 forcePublic.addAll(MethodWrapper.createSet(interfaceMethods)); } methods.addAll(interfaceMethods); } // 过滤掉静态方法 CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC
STATIC)); // 过滤掉不可见的方法(包括两类:私有方法、默认修饰符且与目标类不在同一个包中的方法) CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); // 过滤掉重复的方法(方法名、入参和返回类型都相同的方法) CollectionUtils.filter(methods, new DuplicatesPredicate()); // 过滤掉final方法 CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL)); }

```

```java public class MethodWrapper { private static final MethodWrapper.MethodWrapperKey KEY_FACTORY = (MethodWrapper.MethodWrapperKey)KeyFactory.create(MethodWrapper.MethodWrapperKey.class);

private MethodWrapper() {
}

public static Object create(Method method) {
    return KEY_FACTORY.newInstance(method.getName(), ReflectUtils.getNames(method.getParameterTypes()), method.getReturnType().getName());
}

public static Set createSet(Collection methods) {
    Set set = new HashSet();
    Iterator it = methods.iterator();

    while(it.hasNext()) {
        set.add(create((Method)it.next()));
    }

    return set;
}

public interface MethodWrapperKey {
    Object newInstance(String var1, String[] var2, String var3);
}

} ```

MethodWrapper.MethodWrapperKey的作用是什么呢?

作用是输出方法的方法名、参数类型、返回值,用于比对方法和过滤方法。

java for (Method method : Calculator.class.getMethods()) { System.out.println(MethodWrapper.create(method)); }

输出:

add, {int, int}, int wait,}, void wait, {long, int}, void wait, {long}, void equals, {java.lang.Object}, boolean toString,}, java.lang.String hashCode,}, int getClass,}, java.lang.Class notify,}, void notifyAll,}, void

可以看到这儿也是声明一个写入类 然后按照Ehancer的代理生成策略写入符合的class信息然后返回,最后依旧会执行toByteArray方法返回byte[]数组,这样则又回到了步骤中 根据类加载器 字节码数组来动态将代理类加载进内存中的方法了。最后我们回到根据class获取实例的代码即可返回被代理实例。 而我们执行方法时执行的是代理类中对应的方法,然后调用我们传入的callback执行 原理和jdk动态代理类似,至此 cglib动态代理源码分析到此结束。

Enhancer#create步骤

1.生成指定类的Class对象字节数组

2.将Class对象字节数组转换为Class对象

3.通过 Class.forName 方法将Class对象装载到JVM

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值