略解:AOP 切面編程 —— 動態代理

一、首先要講動態代理,先要從代理模式講起

// 定義公共接口
public interface IShop {

    public void buy();
}
public class MyBuy implements IShop {
    @Override
    public void buy() {
        System.out.print("真正的買東西");
    }
}
public class Static implements IShop {

    private IShop innerShop;

    public Static(IShop innerShop) {
        this.innerShop = innerShop;
    }

    @Override
    public void buy() {
        innerShop.buy();
    }
}
Static s = new Static(new MyBuy());
s.buy();

上面就是代理模式的簡單例子,代理模式的作用有兩個,一個是爲保護真正的是代碼實現類,不讓它直接暴露給客戶,起一箇中介的作用。另一個是可以在代理的過程,給代碼的業務實現加點料,後者一般被拿來做程序員該做的事。

二、動態代理

上面這個代理,需要編譯之前將代理類寫好,打包成.class。而動態代理是在運行時,再生成相應的.class。

先來看動態代理的代碼實現

public class Dynamic implements InvocationHandler {

    private Object object;

    public Dynamic(Object object) {
        this.object = object;
    }

  
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(object, args);
    }
}
IShop shop = new MyBuy();
Dynamic dynamic = new Dynamic(shop);
IShop proxy = (IShop) Proxy.newProxyInstance(shop.getClass().getClassLoader(), new Class[]{IShop.class}, dynamic);
proxy.buy();

核心的代碼就是 Proxy.newProxyInstance()生成一個代理類,並返回它的對象

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
      
        // 生成代理類的.class並獲得對應的Class
        Class<?> cl = getProxyClass0(loader, intfs);

       
        try {
           
            // 獲得構造方法,並且這個構造方法有個參數爲InvocationHandler
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            // 
            if (!Modifier.isPublic(cl.getModifiers())) {
                cons.setAccessible(true);
            }
            // 獲得代理類的實例 等同於 Static s = new Static(new MyBuy());
            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);
        }
    }

getProxyClass0()這個方法在運行時生成一個名爲 公共接口的包名+前綴:“$Proxy"+累計的唯一編碼的數字

class “$Proxy"+累計的唯一編碼的數字 implements IShop{

    InvocationHandler h;

    public “$Proxy"+累計的唯一編碼的數字(InvocationHandler h){
        
        this.h = h;
        ...
    }

    @Override
    public void buy() {
       ...
       this.h.invoke(..);
    }
}

當調用相應接口的方法時,就是調用到invoke方法

相關的源代碼:

class Proxy{
...
    private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // 所有代理類名稱的前綴
        private static final String proxyClassNamePrefix = "$Proxy";

        // 下一個用於生成唯一代理類名稱的數字
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

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

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            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;

           // 獲得包名
            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 the default package.
                proxyPkg = "";
            }

            {
                // Android-changed: Generate the proxy directly instead of calling
                // through to ProxyGenerator.
                List<Method> methods = getMethods(interfaces);
                Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
                validateReturnTypes(methods);
                List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);

                // 獲得接口的方法結合
                Method[] methodsArray = methods.toArray(new Method[methods.size()]);

                // 獲得接口方法拋出異常集合
                Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);

                /*
                 * Choose a name for the proxy class to generate.
                 */
                long num = nextUniqueNumber.getAndIncrement();

                // 拼成代理類的名字
                String proxyName = proxyPkg + proxyClassNamePrefix + num;

                return generateProxy(proxyName, interfaces, loader, methodsArray,
                                     exceptionsArray);
            }
        }
    }
...
}

具體生成.class的代碼實現在native中實現,generateProxy是一個native方法,返回值爲Class。在這個方法中做的事情,大概就是拼一個.class的二進制的文本,並加載進來。

以上就是動態代理的全部核心源代碼實現(Java層),接下來解析其中一個重要的數據結構WeakCache

三、Weakcache

這個數據結構作用:當需要get(..)某個值時,首先在緩存中找,如果緩存中沒有該值,便生成一個值,返回並放入緩存中。在緩存中使用弱引用的方式存儲該值。

這個類的變量

final class WeakCache<K, P, V> {

    private final ReferenceQueue<K> refQueue
        = new ReferenceQueue<>(); // classLeader弱引用對應ReferenceQueue,用於更新map,刪除以回收的key
    // the key type is Object for supporting null key
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
        = new ConcurrentHashMap<>(); // 主存儲map,key值爲外部傳入classleader的弱引用,
value爲以外部傳入公共接口生成CacheKey和對應生成代理cLass<?>構成Map集合
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
        = new ConcurrentHashMap<>(); // 用於存儲代理Class<?>的弱引用的map,起標誌作用
    private final BiFunction<K, P, ?> subKeyFactory; // 通過外部傳入的公共接口生成key值的工廠,
這個key用於上面map的value,即對應的ConcurrentMap
    private final BiFunction<K, P, V> valueFactory;  // 連接native生成代理CLass<?>的工廠
}

Weakcache.get(..)方法

class EakCache{
    ...
    public V get(K key, P parameter) {
        Objects.requireNonNull(parameter);

        // 通過refQueue清理掉已經回收的Classleader
        expungeStaleEntries();

        // 通過對應的Classleader生成CacheKey,作爲map的key,注意:CacheKey重寫hash
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // 從緩存中獲得對應的value,如果不存在,新建一個
        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;
            }
        }

        // 通過外部的接口,生成對應的suKey
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

        // 從緩存中找是否有緩存好的代理Class<?>,即CacheValue對象
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
                // 可能是Factory或CacheValue <V>實例
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            
            // 配置一個ProxyClassFactory,用於生成一個新的代理CLass<?>
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                // 將對應的Factory放入,但在Factory的get方法中會調換
                成代理Class<?>的CacheValue對象(後面說明)
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    supplier = factory;
                }
            } else {
                // 更新
                if (valuesMap.replace(subKey, supplier, factory)) {
                    supplier = factory;
                } else {
                    // 如果替換失敗,換回之前的
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }
    ...
}

上面提到的Factory源代碼:

private final class Factory implements Supplier<V> {

        private final K key;
        private final P parameter;    // 外部傳入接口
        private final Object subKey;   // 外部傳入接口生成的key
        private final ConcurrentMap<Object, Supplier<V>> valuesMap; // map對應的value

        Factory(K key, P parameter, Object subKey,
                ConcurrentMap<Object, Supplier<V>> valuesMap) {
            this.key = key;
            this.parameter = parameter;
            this.subKey = subKey;
            this.valuesMap = valuesMap;
        }

        @Override
        public synchronized V get() { // serialize access
            // 如果緩存裏有,直接使用
            Supplier<V> supplier = valuesMap.get(subKey);
            if (supplier != this) {
                return null;
            }
          
            // 調用native生成新的代理Class<?>
            V value = null;
            try {
                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);

            // 將生成代理Class<?>CacheValue替換原來存進去的Factory
            if (valuesMap.replace(subKey, this, cacheValue)) {
                // 同時也存入reverseMap
                reverseMap.put(cacheValue, Boolean.TRUE);
            } else {
                throw new AssertionError("Should not reach here");
            }

            // successfully replaced us with new CacheValue -> return the value
            // wrapped by it
            return value;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章