天天看點

吃透Spring源碼(十九):CGLIB動态代理建立過程

​ CGLIB(Code Generation Library)是一個開源項目!是一個強大的,高性能,高品質的Code生成類庫,它可以在運作期擴充Java類與實作Java接口。

​ CGLIB是一個強大的高性能的代碼生成包。它廣泛的被許多AOP的架構使用,例如Spring AOP為他們提供方法的interception(攔截)。CGLIB包的底層是通過使用一個小而快的位元組碼處理架構ASM,來轉換位元組碼并生成新的類。除了CGLIB包,腳本語言例如Groovy和BeanShell,也是使用ASM來生成java的位元組碼。當然不鼓勵直接使用ASM,因為它要求你必須對JVM内部結構包括class檔案的格式和指令集都很熟悉。

一,例子準備

MyCalculator.java

public class MyCalculator {
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    public int mult(int i, int j) {
        int result = i * j;
        return result;
    }

    public int div(int i, int j) {
        int result = i / j;
        return result;
    }
}
           

MyCglib.java

public class MyCglib implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object o1 = methodProxy.invokeSuper(o, objects);
        return o1;
    }
}
           

MyTest.java

public class MyTest {
    public static void main(String[] args) {
        //動态代理建立的class檔案存儲到本地
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
        //通過cglib動态代理擷取代理對象的過程,建立調用的對象
        Enhancer enhancer = new Enhancer();
        //設定enhancer對象的父類
        enhancer.setSuperclass(MyCalculator.class);
        //設定enhancer的回調對象
        enhancer.setCallback(new MyCglib());
        //建立代理對象
        MyCalculator myCalculator = (MyCalculator) enhancer.create();
        //通過代理對象調用目标方法
        myCalculator.add(1,1);
        System.out.println(myCalculator.getClass());
    }
}
           

二,實作原理

​ 利用cglib實作動态代理的時候,必須要實作MethodInterceptor接口,此接口源碼如下:

MethodInterceptor.java

public interface MethodInterceptor
extends Callback
{
 	/*
 	此方法用來實作方法的攔截,四個參數分别表示的含義:
 	obj:表示增強的對象,即實作這個接口類的一個對象
 	method:表示要攔截的方法
 	args:表示被攔截的方法的參數
 	proxy:表示要觸發父類的方法對象
 	*/
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
                               MethodProxy proxy) throws Throwable;

}
           

​我們建立了一個cglib的Enhancer對象,并且設定了父類、回調函數等參數,最重要的入口函數是create()方法:

1、Enhancer.create()

/**
     * 如果必須要建立一個新類,那麼就用指定的回調對象建立一個新的對象執行個體,使用的父類的參數的構造方法來實	 * 例化父類的部分
     */
    public Object create() {
        //不作代理類限制
        classOnly = false;
        //沒有構造參數類型
        argumentTypes = null;
        //執行建立
        return createHelper();
    }
           

2、Enhancer.createHelper()

private Object createHelper() {
     	//校驗callbackTypes、filter是否為空,以及為空時的處理
        preValidate();
     	// 通過newInstance方法來建立EnhancerKey對象
        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;
     	// 調用父類即AbstractClassGenerator的建立代理類
        Object result = super.create(key);
        return result;
    }
           

preValidate()

private void preValidate() {
        if (callbackTypes == null) {
            //确定傳入的callback類型
            callbackTypes = CallbackInfo.determineTypes(callbacks, false);
            validateCallbackTypes = true;
        }
        if (filter == null) {
            if (callbackTypes.length > 1) {
                throw new IllegalStateException("Multiple callback types possible but no filter specified");
            }
            filter = ALL_ZERO;
        }
    }
           
private static final CallbackInfo[] CALLBACKS = {
        new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE),
        new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE),
        new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE),
        new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE),
        new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE),
        new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE),
        new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE),
    };
           

​ 該方法主要是做驗證并确定CallBack類型,我們使用的是MethodInterceptor,然後建立目前代理類的辨別代理類,用這個辨別代理類調用(AbstractClassGenerator)的create(key)方法建立,下面我們開始分析辨別代理類建立邏輯 以及後面父類建立我們需要的代理類的邏輯。

​ 辨別代理類的建立類成員變量即KEY_FACTORY是建立代理類的核心

3、辨別代理類

3.1、KEY_FACTORY

​ 追蹤源碼可以看到,KEY_FACTORY在Enhancer的初始化即會建立一個final的靜态變量

private static final EnhancerKey KEY_FACTORY =
      (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);
           
3.2、Keyfactory_create方法

這兒可以看到使用key工廠建立出對應class的代理類,後面的KeyFactory_HASH_ASM_TYPE即代理類中建立HashCode方法的政策。我們接着點選源碼檢視

public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer,
                                    List<KeyFactoryCustomizer> next) {
        //建立一個最簡易的代理類生成器 即隻會生成HashCode equals toString newInstance方法
        Generator gen = new Generator();
        //設定接口為enhancerKey類型
        gen.setInterface(keyInterface);

        if (customizer != null) {
            //添加定制器
            gen.addCustomizer(customizer);
        }
        if (next != null && !next.isEmpty()) {
            for (KeyFactoryCustomizer keyFactoryCustomizer : next) {
                //添加定制器
                gen.addCustomizer(keyFactoryCustomizer);
            }
        }
        //設定生成器的類加載器
        gen.setClassLoader(loader);
        //生成enhancerKey的代理類
        return gen.create();
    }
           
3.3、Generator的create方法

這兒建立了一個簡易的代理類生成器(KeyFactory的内部類Generator ,與Enhancer一樣繼承自抽象類AbstractClassGenerator)來生成我們需要的辨別代理類,我們接着看gen.create()方法

public KeyFactory create() {        
    //設定了該生成器生成代理類的名字字首,即我們的接口名Enhancer.enhancerKey
            setNamePrefix(keyInterface.getName());
            return (KeyFactory)super.create(keyInterface.getName());
        }
           
3.4、AbstractClassGenerator的create(Key)方法
protected Object create(Object key) {
        try {
            //擷取到目前生成器的類加載器
            ClassLoader loader = getClassLoader();
            //目前類加載器對應的緩存  緩存key為類加載器,緩存的value為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) {
                        //建立一個緩存Cache  并将之前的緩存Cache的資料添加進來 并将已經被gc回收的資料給清除掉
                        Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
                        //建立一個目前加載器對應的ClassLoaderData 并加到緩存中  但ClassLoaderData中此時還沒有資料
                        data = new ClassLoaderData(loader);
                        newCache.put(loader, data);
                        //重新整理全局緩存
                        CACHE = newCache;
                    }
                }
            }
            //設定一個全局key 
            this.key = key;
            
            //在剛建立的data(ClassLoaderData)中調用get方法 并将目前生成器,
            //以及是否使用緩存的辨別穿進去 系統參數 System.getProperty("cglib.useCache", "true")  
            //傳回的是生成好的代理類的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);
        }
    }
           

​ 這個方法可以看到主要為根據類加載器定義一個緩存,裡面裝載了緩存的類資訊,然後調用這個ClassLoaderData的get方法擷取到資料,如果為class資訊 那麼直接使用反射執行個體化,如果傳回的是實體類,則解析實體類的資訊,調用其newInstance方法重新生成一個執行個體(cglib的代理類都會生成newInstance方法)

3.5、data.get(this,getUseCache)
public Object get(AbstractClassGenerator gen, boolean useCache) {
            //如果不用緩存  (預設使用)
            if (!useCache) {
                //則直接調用生成器的指令
              return gen.generate(ClassLoaderData.this);
            } else {
              //從緩存中擷取值
              Object cachedValue = generatedClasses.get(gen);
              //解包裝并傳回
              return gen.unwrapCachedValue(cachedValue);
            }
        }
           

​ 如果可以用緩存則調用緩存,不能調用緩存則直接生成, 這兒我們先看調用緩存的,在之前的步驟中,我們設定了一個key為ClassLoader,值為ClassLoaderData的緩存,這兒我們new了一個ClassLoaderData 并将類加載器傳了進去 ,并且設定了這個Generator的key,我們看下new的邏輯

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);
                        }
                    };
            //為這個ClassLoadData建立一個緩存類   這個loadingcache稍後會講        
            generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
        }
        
        
 private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
     public Object apply(AbstractClassGenerator gen) {
         return gen.key;
     }
};
           

​ 可以看到每個類加載器都對應着一個代理類緩存對象 ,這裡面定義了類加載器,緩存調用沒查詢到的調用函數,以及建立了一個LoadingCache來緩存這個類加載器對應的緩存,這兒傳入的兩個參數,load代表緩存查詢失敗時的回調函數,而GET_KEY則是回調時擷取調用生成器的key 即4中傳入的key 也即是我們的代理類辨別符。 然後我們接着看generatedClasses.get(gen);的方法

3.6、generatedClasses.get(gen);

​ 這個方法主要傳入代理類生成器 并根據代理類生成器擷取值傳回。這兒主要涉及到的類就是LoadingCache,這個類可以看做是某個CLassLoader對應的所有代理類緩存庫,是真正緩存東西的地方。我們分析下這個類

public class LoadingCache<K, KK, V> {
    protected final ConcurrentMap<KK, Object> map;
    protected final Function<K, V> loader;
    protected final Function<K, KK> keyMapper;

    public static final Function IDENTITY = new Function() {
        public Object apply(Object key) {
            return key;
        }
    };
    //初始化類  kemapper代表擷取某個代理類生成器的辨別,loader即緩存查找失敗後的回調函數
    public LoadingCache(Function<K, KK> keyMapper, Function<K, V> loader) {
        this.keyMapper = keyMapper;
        this.loader = loader;
        //這個map是緩存代理類的地方
        this.map = new ConcurrentHashMap<KK, Object>();
    }

    @SuppressWarnings("unchecked")
    public static <K> Function<K, K> identity() {
        return IDENTITY;
    }
    //這兒key是代理類生成器
    public V get(K key) {
        //擷取到代理類生成器的辨別
        final KK cacheKey = keyMapper.apply(key);
        //根據緩代理類生成器的辨別擷取代理類
        Object v = map.get(cacheKey);
        //如果結果不為空且不是FutureTask 即線程池中用于擷取傳回結果的接口
        if (v != null && !(v instanceof FutureTask)) {
            //直接傳回
            return (V) v;
        }
        //否則就是沒查詢到  或者還未處理完
        return createEntry(key, cacheKey, v);
    }

    protected V createEntry(final K key, KK cacheKey, Object v) {
        //初始化任務task
        FutureTask<V> task;
        //初始化建立辨別
        boolean creator = false;
        if (v != null) {
            // 則說明這是一個FutureTask 
            task = (FutureTask<V>) v;
        } else {
            //否則還沒開始建立這個代理類  直接建立任務  
            task = new FutureTask<V>(new Callable<V>() {
                public V call() throws Exception {
                    //這兒會直接調用生成器的generate方法
                    return loader.apply(key);
                }
            });
            //将這個任務推入緩存Map  如果對應key已經有則傳回已經有的task,
            Object prevTask = map.putIfAbsent(cacheKey, task);
            //如果為null則代表還沒有建立  辨別更新為true 且運作這個任務
            if (prevTask == null) {
                // creator does the load
                creator = true;
                task.run();
            } 
            //如果是task  說明另一個線程已經建立了task
            else if (prevTask instanceof FutureTask) {
                task = (FutureTask<V>) prevTask;
            } 
            //到這兒說明另一個線程已經執行完了  直接傳回
            else {
                return (V) prevTask;
            }
            
            //上面的一堆判斷主要是為了防止并發出現的問題
        }
        
        V result;
        try {
            //到這兒說明任務執行完并拿到對應的代理類了
            result = task.get();
        } catch (InterruptedException e) {
            throw new IllegalStateException("Interrupted while loading cache item", e);
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException) {
                throw ((RuntimeException) cause);
            }
            throw new IllegalStateException("Unable to load cache item", cause);
        }
        //如果這次執行是建立的
        if (creator) {
            //将之前的FutureTask緩存直接覆寫為實際的代理類資訊
            map.put(cacheKey, result);
        }
        //傳回結果
        return result;
    }
}
           

通過上面的分析可以得知,這個類主要作用是傳入代理類生成器,根據這個代理類生成器以及代理類生成器的key來擷取緩存,如果沒有擷取到則建構一個FutureTask來回調我們之前初始化時傳入的 回調函數,并調用其中的apply方法,而具體調用的則是我們傳入的代理類生成器的generate(LoadClassData)方法,将傳回值覆寫之前的FutureTask成為真正的緩存。是以這個類的主要作用還是緩存。 這樣則和5中不使用緩存時調用了一樣的方法。是以我們接着來分析生成方法 generate(ClassLoadData),這兒因為我們使用的代理類生成器是Genrator,該類沒有重寫generate方法,是以回到了父類AbstractClassGenerator的generate方法

3.7、AbstractClassGenerator.generate 方法
protected Class generate(ClassLoaderData data) {
        Class gen;
        Object save = CURRENT.get();
        //目前的代理類生成器存入ThreadLocal中
        CURRENT.set(this);
        try {
            //擷取到ClassLoader
            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) {
                    // 發現異常說明沒加載到 不管了
                }
            }
            //生成位元組碼
            byte[] b = strategy.generate(this);
            //擷取到位元組碼代表的class的名字
            String className = ClassNameReader.getClassName(new ClassReader(b));
            //核實是否為protect
            ProtectionDomain protectionDomain = getProtectionDomain();
            synchronized (classLoader) { // just in case
                //如果不是protect
                if (protectionDomain == null) {
                    //根據位元組碼 類加載器 以及類名字  将class加載到記憶體中
                    gen = ReflectUtils.defineClass(className, b, classLoader);
                } else {
                    //根據位元組碼 類加載器 以及類名字 以及找到的Protect級别的實體 将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);
        }
    }
           

​ 這個方法主要設定了下目前類生成器的類名,然後調用stratege的generate方法傳回位元組碼,根據位元組碼 類名 類加載器将位元組碼所代表的類加載到記憶體中,這個功能看一下大概就懂,我們接下來主要分析位元組碼生成方法

3.8、DefaultGeneratorStrategy.generate(ClassGenerator cg)
public byte[] generate(ClassGenerator cg) throws Exception {
        //建立一個寫入器
        DebuggingClassWriter cw = getClassVisitor();
        //加入自己的轉換邏輯後執行代理類生成器的generateClass方法
        transform(cg).generateClass(cw);
        //将cw寫入的東西轉換為byte數組傳回
        return transform(cw.toByteArray());
    }
           

​ 這裡面主要是建立一個寫入器,然後執行我們代理類生成器的generateClass方法将class資訊寫入這個ClassWriter 最後将裡面的東西轉換為byte數組傳回,是以又回到了我們的代理類生成器的generateClass方法,這兒進入的是Generator的generateClass方法

3.9、Generator.generateClass(ClassVisitor v)
//該方法為位元組碼寫入方法 為最後一步
 public void generateClass(ClassVisitor v) {
            //建立類寫入聚合對象
            ClassEmitter ce = new ClassEmitter(v);
            //找到被代理類的newInstance方法 如果沒有會報異常  由此可知 如果想用Generator代理類生成器  必須要有newInstance方法
            Method newInstance = ReflectUtils.findNewInstance(keyInterface);
            //如果被代理類的newInstance不為Object則報異常  此處我們代理的Enchaer.EnhancerKey newInstance方法傳回值為Object
            if (!newInstance.getReturnType().equals(Object.class)) {
                throw new IllegalArgumentException("newInstance method must return Object");
            }
            //找到newInstance方法的所有參數類型 并當做成員變量 
            Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
            
            //1.建立類開始寫入類頭   版本号  通路權限  類名等通用資訊
            ce.begin_class(Constants.V1_8,
                           Constants.ACC_PUBLIC,
                           getClassName(), 
                           KEY_FACTORY,
                           new Type[]{ Type.getType(keyInterface) },
                           Constants.SOURCE_FILE);
            //2.寫入無參構造方法               
            EmitUtils.null_constructor(ce);
            //3.寫入newInstance方法
            EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
            
            int seed = 0;
            //4.開始構造 有參構造方法
            CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
                                            TypeUtils.parseConstructor(parameterTypes),
                                            null);
            e.load_this();
            //4.1有參構造中調用父類構造方法  即super.構造方法() 
            e.super_invoke_constructor();
            e.load_this();
            //4.2找到傳入的定制器 例如一開始傳入的hashCode方法定制器
            List<FieldTypeCustomizer> fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class);
            //4.3周遊成員變量即newInstance方法的所有參數
            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();
                //4.3将這些參數全部聲明到寫入類中
                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);
                }
                //4.4設定每個成員變量的值  即我們常見的有參構造中的this.xx = xx
                e.putfield(getFieldName(i));
            }
            //設定傳回值
            e.return_value();
            //有參構造及成員變量寫入完成
            e.end_method();
            
            /*************************到此已經在class中寫入了成員變量  寫入實作了newInstance方法  寫入無參構造  寫入了有參構造 *************************/
            
            // 5.寫入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();
            //hashcode方法結束
            e.end_method();

            // 6.寫入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();
            //equals方法結束
            e.end_method();

            // 7.寫入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();
            //toString方法結束
            e.end_method();
            //類寫入結束  至此類資訊收集完成 并全部寫入ClassVisitor
            ce.end_class();
        }
           

​ 這個方法主要将一個完整的類資訊寫入ClassVisitor中,例如目前實作的Enhancer.EnhancerKey代理,即實作了newInstance方法, 重寫了HashCode,toSting,equals方法,并将newInstance的所有參數作為了成員變量,這兒我們也可以看下具體實作newInstance方法的邏輯 即這個代碼 EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance)); 如果有興趣可以去研究asm位元組碼寫入的操作

public static void factory_method(ClassEmitter ce, Signature sig) 
    {
        //開始寫入方法
        CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, sig, null);
        //寫入 一個建立對象指令  即new指令
        e.new_instance_this();
        e.dup();
        //加載參數指令
        e.load_args();
        //執行該類的有參構造指令
        e.invoke_constructor_this(TypeUtils.parseConstructor(sig.getArgumentTypes()));
        //将上面指令執行的值傳回
        e.return_value();
        //結束寫入方法
        e.end_method();
    }
           

​ 可以得知 我們通過Generator建立的代理類大緻内容應該如下,Enhancer.EhancerKey代理類位元組碼的class内容應該是把參數換為newInstance中的參數

public class EnhancerKeyProxy extends xxx implements xxx{

 private paramA;
 private paramB;
 private paramC;
 
 public EnhancerKeyProxy() {
         super.xxx();
 }
 public EnhancerKeyProxy(paramA, paramB,paramC) {
       super.xxx();
       this.paramA = paramA
       this.paramB = paramB
       this.paramC = paramC
    }

 public Object newInstance(paramA,paramB,paramC){
        EnhancerKeyProxy param = new EnhancerKeyProxy(o);
        return param;
 }
 
  public int hashCode(){
      ...
  }
   public String toString(){
      ...
  }
  
  public boolean equals(Object o){
      ...
  }

}
           

​ 最後執行傳入的ClassVisitor 即我們傳入的執行個體DebuggingClassWriter的toByteArray即可以将寫入的内容轉換為byte[]傳回

​ 至此 我們的成功的生成了Enhancer.EnhancerKey的代理類,也就是我們需要的代理類辨別類 用來辨別被代理的類,這個代理類主要用來作為被代理類的辨別,在進行緩存時作為判斷相等的依據。可以看到 cglib代理主要也是利用我們傳入的被代理類資訊來生成對應的代理類位元組碼,然後用類加載器加載到記憶體中。雖然我們的實際的代理任務才剛剛開始,但是要了解的東西已經基本上差不多了,對具體的我們案例中的ProxyFactory代理時,隻是生成器Enhancer對比生成器Generator在生成過程中重寫了一些操作而已。

4、回到步驟2,接着向下看執行的過程

private Object createHelper() {
        preValidate();
        //擷取到了代理類辨別類
        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正在代理生成的類資訊
        this.currentKey = key;
        //調用父類的create(key方法)
        Object result = super.create(key);
        return result;
    }
           

​ 可以看到擷取到代理類标志類後 将其設定為目前代理類生成器的正在代理的類 并同樣調用父類AbstractClassGenerator中create(key)的方法,下面開始分析Ehancer生成器的邏輯,由于部分邏輯和Generator生成器一緻

5、AbstractClassGenerator.create方法

​ 這個邏輯和上述步驟一緻,查詢目前key即代理類标志類對應的ClassLoadData緩存,如果沒有則建一個空的緩存并初始化一個對應的ClassLoadData,傳入相應的生成器,生成失敗回調函數等

按照同樣的邏輯一直走到generate(ClassLoadData)方法時,由于Enhancer生成器重寫了這個方法 是以我們分析Enahncer的生成邏輯

6、Enhancer.generate(ClassLoadData data)

@Override
    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);
    }
           

​ 可以發現ehancer生成器隻是做了個檢查命名操作 在上面的Generator中也是做了個命名操作,然後繼續執行父類的generate(data)方法,這個和上述步驟一緻,我們主要看其中生成位元組碼的方法,即最後調用的Enhancer.generatorClass(ClassVisitor c)方法,

7、Enhancer.generatorClass(ClassVisitor c)

public void generateClass(ClassVisitor v) throws Exception {
        //聲明需代理的類 或者接口
        Class sc = (superclass == null) ? Object.class : superclass;
        //檢查 final類無法被繼承
        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();
        //聲明所有必須為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:ThreadLocal
        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();
           

​ 可以看到這兒也是聲明一個寫入類 然後按照Ehancer的代理生成政策寫入符合的class資訊然後傳回,最紅依舊會執行toByteArray方法傳回byte[]數組,這樣則又回到了步驟中 根據類加載器 位元組碼數組來動态将代理類加載進記憶體中的方法了。最後我們回到根據class擷取執行個體的代碼即可傳回被代理執行個體。 而我們執行方法時執行的是代理類中對應的方法,然後調用我們傳入的callback執行 原理和jdk動态代理類似,至此 cglib動态代理源碼分析到此結束。

繼續閱讀