略解: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;
        }
    }

 

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