解析Java动态代理机制的实现

简介

代理模式主要是Proxy对原始方法做了一层包装,用以增加一些新的统一处理逻辑,来增强目标对象的功能。静态代理是传统设计模式中一种传统的实现方案,动态代理能将代理对象的创建延迟到程序运行阶段。

以下是一个动态代理的示例:

被代理类:

public interface DemoService {

    public String process(String value);
}


@Slf4j
public class DemoServiceImpl implements DemoService{

    public static final String RESULT = "result";

    @Override
    public String process(String value) {
        log.info("{} is processing, parameter: {}", this.getClass().getName(), value);
        return RESULT;
    }
}

代理类:

@Slf4j
public class DemoInvokerHandler implements InvocationHandler {

    private final Object target;

    public DemoInvokerHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("before...");
        Object result = method.invoke(target, args);
        log.info("after...");
        return result;
    }

    public Object getProxy() {
        // 创建代理对象
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);

    }
}

代理调用:

@Slf4j
public class ProxyMain {

    public static void main(String[] args) {
        DemoService service = new DemoServiceImpl();
        DemoInvokerHandler demoInvokerHandler = new DemoInvokerHandler(service);
        DemoService proxy = (DemoService) demoInvokerHandler.getProxy();
        String result = proxy.process("test");
        log.info("result is : {}", result);
    }
}

动态代理实现原理

通过上述示例中getProxy()方法可以看出,创建代理对象的核心方法是:

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException

传入参数分别为:

  • loader:加载动态代理类的classloader
  • interfaces:代理目标的接口类型
  • h:InvocationHandler类型,用于执行代理目标的方法时,触发的handler

该方法的具体实现与注释如下:

{
        Objects.requireNonNull(h);

    	//检查classloader、包权限等
        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.
         */
    	//获取代理类class
        Class<?> cl = getProxyClass0(loader, intfs);

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

            //获取代理类的构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            //Q:这里赋值ih的意义是什么
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            //创建代理对象
            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);
        }
    }

加载Class对象是通过getProxyClass0()方法实现的:

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
        return proxyClassCache.get(loader, interfaces);
    }

proxyClassCache用于缓存已经创建过的代理类,定义如下:

private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

代理类缓存WeakCache

WeakCache是上述缓存proxyClassCache的具体实现,WeakCache包含以下字段:

  • refQueue:ReferenceQueue类型,用于存储被回收的key
    • ReferenceQueue:用于处理弱引用、软引用和虚引用的回收操作,当对象被GC后,可以从queue中获取对应的对象信息,进行其他处理。
  • map:ConcurrentMap类型,存储键值对的map,有两级缓存,存储结构为:key -> (subKey -> value)
    • 一级缓存的key为classloader
    • 二级缓存为KeyFactory为代理类的接口数组生成的key,包括key0、key1、key2、keyx
  • reverseMap:记录了所有可用的代理类,key为代理类的cacheValue
  • subKeyFactory:BiFunction函数式接口,生成subKey的工厂类,Proxy类传入:java.lang.reflect.Proxy.KeyFactory
  • valueFactory:BiFunction函数式接口,生成value的工厂类,Proxy类传入:java.lang.reflect.Proxy.ProxyClassFactory
 /*
 * @author Peter Levart
 * @param <K> type of keys
 * @param <P> type of parameters
 * @param <V> type of values
 */
final class WeakCache<K, P, V> {

    private final ReferenceQueue<K> refQueue
        = new ReferenceQueue<>();
    // the key type is Object for supporting null key
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
        = new ConcurrentHashMap<>();
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
        = new ConcurrentHashMap<>();
    private final BiFunction<K, P, ?> subKeyFactory;
    private final BiFunction<K, P, V> valueFactory;
}

KeyFactory

java.lang.reflect.Proxy.KeyFactory是用于生成二级cache的subKey的工厂类,返回的对象为WeakReference

private static final class KeyFactory
        implements BiFunction<ClassLoader, Class<?>[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
            switch (interfaces.length) {
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }


private static final class Key1 extends WeakReference<Class<?>> {}
    
private static final class Key2 extends WeakReference<Class<?>> {}

private static final class KeyX {
        private final int hash;
        private final WeakReference<Class<?>>[] refs;
}

ProxyClassFactory

java.lang.reflect.Proxy.ProxyClassFactory根据传入classloader和接口类数组,返回代理类的工厂。主要流程如下:

  • 校验参数的正确性:
    • 校验classloader加载的接口类和传入接口是否为同一个
    • 校验是否为接口类
    • 校验接口是否重复
    • 判断接口的权限修饰符,非public接口的代理类包名取接口类的包名,public取com.sun.proxy
  • 设置代理类的包名:包名 + \(Proxy + 原子递增数字 - 例如:`com.sun.proxy.\)Proxy0`
  • 调用ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags)生成class文件
  • 调用native方法defineClass0()将class文件加载到JVM

WeakCache#get

java.lang.reflect.Proxy#getProxyClass0中调用get(loader, interfaces),传入的key为ClassLoader类型,parameter为Class<?>类型,为代理类接口。主要流程如下:

  • 参数校验、执行expungeStaleEntries()清理过期对象
  • 使用一级cache的key获取二级cache的map对象
  • 向KeyFactory传入key和parameter,生成二级cache的key
  • 轮询获取supplier中的value
    • 如果supplier为空,将当前subKey对应的数据设置为Factory实例。
    • Factory会通过ProxyClassFactory生成代理类
public V get(K key, P parameter) {
        Objects.requireNonNull(parameter);

        expungeStaleEntries();
		//包装classloader,生成一级cache的key
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey
    	//获取二级cache的map对象
        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));
    	//获取二级cache的值
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;
		//轮询获取supplier中的value
        while (true) {
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                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) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }
			//二级cache直接放入subKey -> factory的映射
            //设置supplier = factory
            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    // successfully installed Factory
                    supplier = factory;
                }
                // else retry with winning supplier
            } else {
                //轮询时如果其他线程已经设置了值的情况
                //替换为factory
                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);
                }
            }
        }
    }

Factory

通过Factory实例调用ProxyClassFactory.apply(key, parameter)生成代理类,通过synchronized保证线程安全,get()的具体逻辑参考注释:

private final class Factory implements Supplier<V> {
		//一级cache的key,为classloader
        private final K key;
    	//代理类的接口数组
        private final P parameter;
    	//二级cache的key,根据接口数组生成
        private final Object subKey;
    	//二级缓存的引用
        private final ConcurrentMap<Object, Supplier<V>> valuesMap;

        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
            // re-check
            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 {
                //通过ProxyClassFactory去生成代理类
                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;
        }
    }

解析Java动态代理机制的实现
https://l1n.wang/2023/Java基础/解析Java动态代理机制/
作者
Lin Wang
发布于
2023年3月5日
许可协议