Jdk動(dòng)態(tài)代理 底層源碼分析

文章已遷移至https://blog.csdn.net/chaitoudaren/article/details/104833279

前言

java動(dòng)態(tài)代理主要有2種,Jdk動(dòng)態(tài)代理、Cglib動(dòng)態(tài)代理,本文主要講解Jdk動(dòng)態(tài)代理的使用、運(yùn)行機(jī)制、以及源碼分析。當(dāng)spring沒(méi)有手動(dòng)開(kāi)啟Cglib動(dòng)態(tài)代理,即:<aop:aspectj-autoproxy proxy-target-class="true"/>@EnableAspectJAutoProxy(proxyTargetClass = true),默認(rèn)使用的就是Jdk動(dòng)態(tài)代理。動(dòng)態(tài)代理的應(yīng)用范圍很廣,例如:日志、事務(wù)管理、緩存等。本文將模擬@Cacheable,即緩存在動(dòng)態(tài)代理中的應(yīng)用進(jìn)行講解。需要注意的是,Jdk動(dòng)態(tài)代理相比起cglib動(dòng)態(tài)代理,Jdk動(dòng)態(tài)代理的對(duì)象必須實(shí)現(xiàn)接口,否則將報(bào)錯(cuò)。我們也將帶著這個(gè)問(wèn)題在源碼分析中尋找答案

當(dāng)@Cacheable注解在方法上時(shí)

  1. 在方法執(zhí)行前,將調(diào)用Jdk動(dòng)態(tài)代理優(yōu)先查找Redis(或其他緩存)
  2. 當(dāng)緩存不存在時(shí),執(zhí)行方法,例如查詢數(shù)據(jù)庫(kù)
  3. 在方法執(zhí)行后,再次調(diào)用Jdk動(dòng)態(tài)代理,將結(jié)果緩存到Redis中

一、使用

步驟

  1. 創(chuàng)建接口UserService
  2. 創(chuàng)建接口實(shí)現(xiàn)類UserServiceImpl
  3. 創(chuàng)建Jdk動(dòng)態(tài)代理JdkCacheHandler,用于增強(qiáng)UserServiceImpl方法前后的緩存邏輯

代碼

  1. 創(chuàng)建接口UserService
public interface UserService {
    public String getUserByName(String name);
}
  1. 創(chuàng)建實(shí)現(xiàn)類UserServiceImpl
public class UserServiceImpl implements UserService {
    @Override
    public String getUserByName(String name) {
        System.out.println("從數(shù)據(jù)庫(kù)中查詢到:" + name);
        return name;
    }
}
  1. 創(chuàng)建Jdk動(dòng)態(tài)代理JdkCacheHandler
public class JdkCacheHandler implements InvocationHandler {

    // 目標(biāo)類對(duì)象
    private Object target;

    // 獲取目標(biāo)類對(duì)象
    public JdkCacheHandler(Object target) {
        this.target = target;
    }

    // 創(chuàng)建JDK代理
    public Object createJDKProxy() {
        Class clazz = target.getClass();
        // 創(chuàng)建JDK代理需要3個(gè)參數(shù),目標(biāo)類加載器、目標(biāo)類接口、代理類對(duì)象(即本身)
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:" + args[0]);
        // 觸發(fā)目標(biāo)類方法
        Object result = method.invoke(target, args);
        System.out.printf("查找數(shù)據(jù)庫(kù)后,將%s加入到緩存中\(zhòng)r\n", result);
        return result;
    }
}
  1. 創(chuàng)建測(cè)試類
public class JdkTest {

    @Test
    public void test() {
        UserService userService = new UserServiceImpl();
        JdkCacheHandler jdkCacheHandler = new JdkCacheHandler(userService);
        UserService proxy = (UserService) jdkCacheHandler.createJDKProxy();

        System.out.println("==========================");
        proxy.getUserByName("bugpool");
        System.out.println("==========================");

        System.out.println(proxy.getClass());
    }
}
  1. 輸出
==========================
查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:bugpool
從數(shù)據(jù)庫(kù)中查詢到:bugpool
查找數(shù)據(jù)庫(kù)后,將bugpool加入到緩存中
==========================
class com.sun.proxy.$Proxy4

二、調(diào)用機(jī)制

查看$Proxy代碼

可以看到當(dāng)經(jīng)過(guò)Jdk動(dòng)態(tài)代理以后,生產(chǎn)的proxy已經(jīng)不再是UserService類型了,而是$Proxy4類型,想要了解其調(diào)用機(jī)制,得先獲取到proxy類的代碼

System.out.println(proxy.getClass());

class com.sun.proxy.$Proxy4
  1. 修改JVM運(yùn)行參數(shù),添加-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
    修改JVM運(yùn)行參數(shù).png

    添加JVM運(yùn)行參數(shù).png
  2. 運(yùn)行test即可在com.sun.proxy查看代碼,此時(shí)生產(chǎn)的是class,idea打開(kāi)會(huì)自動(dòng)反編譯


    Proxy代碼.png
  3. 在上方輸出中可以看到代理類是$Proxy4,至此獲取到$Proxy4的源代碼,接下去分析代理類的調(diào)用機(jī)制
public final class $Proxy4 extends Proxy implements UserService {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy4(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String getUserByName(String var1) throws  {
        try {
            return (String)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("proxy.jdk.UserService").getMethod("getUserByName", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

調(diào)用機(jī)制

  1. 從proxy調(diào)用開(kāi)始
// JdkTest.java
proxy.getUserByName("bugpool");
  1. proxy是$Proxy4類型,因此進(jìn)入$Proxy4的getUserByName方法
// $Proxy4.class
public final class $Proxy4 extends Proxy implements UserService {
    ...

    // 構(gòu)造器,傳入JdkCacheHandler類的對(duì)象,正是下方調(diào)用的super.h屬性
    public $Proxy4(InvocationHandler var1) throws  {
        super(var1);
    }

    public final String getUserByName(String var1) throws  {
        try {
            /**
            *   調(diào)用父類的h屬性的invoke方法
            *   在下面的源碼分析中,會(huì)發(fā)現(xiàn)h屬性正是JdkCacheHandler類createJDKProxy方法中所傳入的this
            *   Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
            *   而this指代的正是JdkCacheHandler類的對(duì)象,因此最后調(diào)用的是JdkCacheHandler的invoke方法
            */
            return (String)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    ...

    static {
        ...
        m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
        m3 = Class.forName("proxy.jdk.UserService").getMethod("getUserByName", Class.forName("java.lang.String"));
        m2 = Class.forName("java.lang.Object").getMethod("toString");
        m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        ...
    }
}
  1. 因此h.invok實(shí)際調(diào)用的正是JdkCacheHandler類的invoke方法
// JdkCacheHandler.java
public class JdkCacheHandler implements InvocationHandler {
    ...
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:" + args[0]);
        // 觸發(fā)目標(biāo)類方法
        Object result = method.invoke(target, args);
        System.out.printf("查找數(shù)據(jù)庫(kù)后,將%s加入到緩存中\(zhòng)r\n", result);
        return result;
    }
}
  1. method.invoke(target, args)中的method = getUserByName,target = 構(gòu)造函數(shù)傳進(jìn)來(lái)的UserServiceImpl對(duì)象,args = "bugpool"
// UserServiceImpl.java
public class UserServiceImpl implements UserService {
    @Override
    public String getUserByName(String name) {
        System.out.println("從數(shù)據(jù)庫(kù)中查詢到:" + name);
        return name;
    }
}

三、源碼分析

原理

了解完Jdk動(dòng)態(tài)代理的調(diào)用機(jī)制,所有核心問(wèn)題都落在了$Proxy4類的對(duì)象proxy是如何生成的上面?即下面這句代碼上,這里先給出概述,有利于宏觀上看源碼。在開(kāi)始之前先復(fù)習(xí)一下java的運(yùn)行機(jī)制:1. 所有.java文件經(jīng)過(guò)編譯生成.class文件 2. 通過(guò)類加載器classLoad將.class中的字節(jié)碼加載到JVM中 3. 運(yùn)行

// 創(chuàng)建JDK代理
public Object createJDKProxy() {
    Class clazz = target.getClass();
    // 創(chuàng)建JDK代理需要3個(gè)參數(shù)
    // 目標(biāo)類加載器:用于加載生成的字節(jié)碼
    // 目標(biāo)類接口:用于生成字節(jié)碼,也就是說(shuō)$Proxy的生產(chǎn)僅僅需要接口數(shù)組就可以完成
    // 代理類對(duì)象(即本身):用于回調(diào)invoke方法,實(shí)現(xiàn)方法的增強(qiáng)
    return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
  1. 通過(guò)clazz.getInterfaces()獲取到所有接口,通過(guò)接口可以生成類似以下字節(jié)碼(注意以下給出的是代碼),細(xì)細(xì)觀察會(huì)發(fā)現(xiàn)其實(shí)各個(gè)接口方法生成的代碼都是一樣的,只有(String)super.h.invoke(this, m3, new Object[]{var1}的m3和參數(shù)有可能是不同的。所以其實(shí)想生成$Proxy字節(jié)碼,只需要接口數(shù)組就已經(jīng)完全足夠了
public final String getUserByName(String var1) throws  {
        try {
            return (String)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
  1. 此時(shí)已經(jīng)獲取到$Proxy4.class的字節(jié)碼,但是此處的字節(jié)碼還未加載到JVM中,因此需要調(diào)用clazz.getClassLoader()傳進(jìn)來(lái)的類加載器進(jìn)行加載,并得到對(duì)應(yīng)的class,也就是$Proxy類
  2. 獲取$Proxy類的構(gòu)造函數(shù),該構(gòu)造函數(shù)有一個(gè)重要的參數(shù)h
  3. 通過(guò)反射調(diào)用$Proxy類的構(gòu)造函數(shù),cons.newInstance(new Object[]{h});構(gòu)造函數(shù)的h正是傳入的this,也就是JdkCacheHandler類的對(duì)象
  4. 將反射獲取到的$Proxy對(duì)象放回

源碼分析

  1. Proxy.newProxyInstance開(kāi)始跟蹤代碼(注:①代表上方概述的步驟1)
// JdkCacheHandler.java
// 創(chuàng)建JDK代理
public Object createJDKProxy() {
    Class clazz = target.getClass();
    // 創(chuàng)建JDK代理需要3個(gè)參數(shù),目標(biāo)類加載器、目標(biāo)類接口、代理類對(duì)象(即本身)
    return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
  1. 跟蹤代碼newProxyInstance,這里需要注意在①②過(guò)程結(jié)束后,③④過(guò)程調(diào)用前,即Class<?> cl = getProxyClass0(loader, intfs);結(jié)束后,cl變量一直都只是class,即$Proxy4類,并未生成對(duì)應(yīng)的對(duì)象,這里不要混淆類和對(duì)象
// Proxy.java
// loader類加載器,interfaces目標(biāo)類實(shí)現(xiàn)的所有接口,h即InvocationHandler類的對(duì)象
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        // 校驗(yàn)InvocationHandler是否為空
        Objects.requireNonNull(h);

        // 該目標(biāo)類實(shí)現(xiàn)的接口數(shù)組
        final Class<?>[] intfs = interfaces.clone();
        // 安全檢查
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        // 當(dāng)緩存中存在代理類則直接獲取,否則生成代理類
        // ①②步驟,核心代碼,即生成代理類字節(jié)碼以及加載都在這里進(jìn)行
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            // ③ 從生成的代理類中獲取構(gòu)造函數(shù)
            // constructorParams = { InvocationHandler.class };
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // ④ 調(diào)用構(gòu)造函數(shù),將InvocationHandler作為參數(shù)實(shí)例化代理對(duì)象
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }
  1. 跟蹤Class<?> cl = getProxyClass0(loader, intfs);
// Proxy.java
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }

    // If the proxy class defined by the given loader implementing
    // the given interfaces exists, this will simply return the cached copy;
    // otherwise, it will create the proxy class via the ProxyClassFactory
    // 如果在類加載器中已經(jīng)存在實(shí)現(xiàn)了對(duì)應(yīng)接口的代理類,則直接返回緩存中的代理類
    // 否則,通過(guò)ProxyClassFactory新建代理類
    return proxyClassCache.get(loader, interfaces);
}
  1. 跟蹤proxyClassCache.get(loader, interfaces);(注:Jdk動(dòng)態(tài)代理對(duì)已經(jīng)生成加載過(guò)的代理類進(jìn)行了緩存以提高性能,緩存的相關(guān)代碼不是我們關(guān)心的重點(diǎn),可以跳過(guò)相關(guān)代碼)本段代碼我們主要關(guān)心V value = supplier.get();其中supplier本質(zhì)是factory,通過(guò)new Factory(key, parameter, subKey, valuesMap)創(chuàng)建
// WeakCache.java
//K和P就是WeakCache定義中的泛型,key是類加載器,parameter是接口類數(shù)組
public V get(K key, P parameter) {
        // 檢查接口數(shù)組是否為空
        Objects.requireNonNull(parameter);

        expungeStaleEntries();

        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        //通過(guò)sub-key得到supplier,實(shí)質(zhì)就是factory
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                // ①②步驟都在這里,如果supplier不為空,則直接調(diào)用get方法返回代理類
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            // else no supplier in cache
            // or a supplier that returned null (could be a cleared CacheValue
            // or a Factory that wasn't successful in installing the CacheValue)

            // lazily construct a Factory
            if (factory == null) {
                // 創(chuàng)建對(duì)應(yīng)factory,此段代碼在死循環(huán)中,下一次supplier.get()將會(huì)獲取到代理類并退出循環(huán)
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    // successfully installed Factory
                    // 賦值給supplier
                    supplier = factory;
                }
                // else retry with winning supplier
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    // successfully replaced
                    // cleared CacheEntry / unsuccessful Factory
                    // with our Factory
                    supplier = factory;
                } else {
                    // retry with current supplier
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }
  1. 跟蹤V value = supplier.get();即Factory類的get方法,這里大部分的工作還是在做校驗(yàn)和緩存,我們只關(guān)心核心邏輯valueFactory.apply(key, parameter);其中valueFactory是上一個(gè)步驟傳入的ProxyClassFactory
// Factory.java    
public synchronized V get() { // serialize access
        // re-check
        // 再次檢查,supplier是否是當(dāng)前對(duì)象
        Supplier<V> supplier = valuesMap.get(subKey);
        if (supplier != this) {
            // something changed while we were waiting:
            // might be that we were replaced by a CacheValue
            // or were removed because of failure ->
            // return null to signal WeakCache.get() to retry
            // the loop
            return null;
        }
        // else still us (supplier == this)

        // create new value
        V value = null;
        try {
            // valueFactory 是前序傳進(jìn)來(lái)的 new ProxyClassFactory()
            // ①②步驟,核心邏輯,調(diào)用valueFactory.apply生成對(duì)應(yīng)代理類并加載
            value = Objects.requireNonNull(valueFactory.apply(key, parameter));
        } finally {
            if (value == null) { // remove us on failure
                valuesMap.remove(subKey, this);
            }
        }
        // the only path to reach here is with non-null value
        assert value != null;

        // wrap value with CacheValue (WeakReference)
        CacheValue<V> cacheValue = new CacheValue<>(value);

        // put into reverseMap
        reverseMap.put(cacheValue, Boolean.TRUE);

        // try replacing us with CacheValue (this should always succeed)
        if (!valuesMap.replace(subKey, this, cacheValue)) {
            throw new AssertionError("Should not reach here");
        }

        // successfully replaced us with new CacheValue -> return the value
        // wrapped by it
        return value;
    }
  1. 跟蹤核心邏輯
    • Jdk動(dòng)態(tài)代理通過(guò)拼湊的方式拼湊出$Proxy的全類名:com.sun.proxy.$proxy0.class
    • ③生產(chǎn)字節(jié)碼byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);可以看出Jdk動(dòng)態(tài)代理需要interfaces接口數(shù)組進(jìn)行生成字節(jié)碼,這也是文章開(kāi)頭提出為什么必須實(shí)現(xiàn)接口的原因。同時(shí)從參數(shù)也可以看出需要生成字節(jié)碼其實(shí)只需要接口數(shù)組,不需要其他信息。其實(shí)實(shí)現(xiàn)原理大概也可以猜出,Jdk動(dòng)態(tài)代理通過(guò)遍歷所有接口方法,為方法生成對(duì)應(yīng)的return (String)super.h.invoke(this, m0~n, new Object[]{var1});代碼
    • ④加載字節(jié)碼:在③中獲取到了字節(jié)碼的字節(jié)數(shù)組,接下去就是調(diào)用classLoader將所有的字節(jié)碼讀入到JVM中
// ProxyClassFactory.java
private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // prefix for all proxy class names
        // 代理類名稱前綴
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names
        // 代理類計(jì)數(shù)器
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            // 校驗(yàn)代理類接口
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            // 代理類包名
            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            // 當(dāng)接口修飾符是public,則所有包都可以使用
            // 當(dāng)接口是非public,則生成的代理類必須和接口在與非public接口同一個(gè)包下
            // 如果非public的接口均在同一個(gè)包下,則生成的代理類放在非public接口同一個(gè)包下
            // 而如果非public的接口存在多個(gè),且在不同包下,則拋出異常
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                // 如果都是公有的接口,則代理類默認(rèn)放在com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             */
            // 生成計(jì)數(shù)器,例如$proxy0~n
            long num = nextUniqueNumber.getAndIncrement();
            // 代理類名,com.sun.proxy.$proxy0.class
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.
             */
            // ③生成代理類字節(jié)碼
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                // ④使用傳進(jìn)來(lái)的classLoader將代理類字節(jié)碼加載到JVM中
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容