动态代理源码分析

时间:2021-6-4 作者:qvyue
动态代理步骤

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法

2.创建被代理的类以及接口

3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理

4.通过代理调用方法

    IRoom xiaoMing = new XiaoMing();
    InvocationHandler invocationHandler = new DynamicProxy(xiaoMing);
    ClassLoader classLoader = xiaoMing.getClass().getClassLoader();
    IRoom proxy = (IRoom) Proxy.newProxyInstance(classLoader,new Class[]{IRoom.class},invocationHandler);
    proxy.seekRoom();
    proxy.watchRoom();
    proxy.room();        
        
    public class DynamicProxy implements InvocationHandler {
    private Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object,args);
        return result;
    }
}

通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理对象。

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

        final Class>[] intfs = interfaces.clone();
        Class> cl = getProxyClass0(loader, intfs);//1

        try {

            final Constructor> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                cons.setAccessible(true);//2
            }
            return cons.newInstance(new Object[]{h});//3
        } 
    }

先对h进行判空处理。

从1可知,先接口得到接口类,

private static Class> getProxyClass0(ClassLoader loader,
                                           Class>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        return proxyClassCache.get(loader, interfaces);
    }

当接口的数量超过65535,则报异常。

proxyClassCache 是一个弱引用的缓存

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

继续看它的get();

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

        expungeStaleEntries();

        //把key封装成CacheKey
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        //通过CacheKey得到valuesMap
        ConcurrentMap> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
        //如果valuesMap不存在通过全局map获取,如果获取到的直接赋值给valueMap
            ConcurrentMap> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        //根据subKey得到supplier
        Supplier supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
        //如果supplier不为null,则直接调用get()获取
            if (supplier != null) {
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
           //为null的情况下,new 一个Factory。Factory是实现Supplier接口。
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    supplier = factory;
                }
                
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    supplier = factory;
                } else {
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }

接下来看supplier的get()

public synchronized V get() { 
            Supplier supplier = valuesMap.get(subKey);
            if (supplier != this) {
                return null;
            }
            
            V value = null;
            try {
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { // remove us on failure
                    valuesMap.remove(subKey, this);
                }
            }
            
            CacheValue cacheValue = new CacheValue(value);

            if (valuesMap.replace(subKey, this, cacheValue)) {
                reverseMap.put(cacheValue, Boolean.TRUE);
            } else {
                throw new AssertionError("Should not reach here");
            }
            return value;
        }

首先看proxyClassCache的定义WeakCache[], Class>>,泛型里面第一个表示加载器K,第二个表示接口类P,第三个则是生成的代理类V。

而V的生成则是通过ProxyClassFactory生成的。调用其apply();

public Class> apply(ClassLoader loader, Class>[] interfaces) {

            ////将所有的接口对象都存到map中,并且不能有重复
            Map, Boolean> interfaceSet = new IdentityHashMap(interfaces.length);
            for (Class> intf : interfaces) {
                
                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");
                }
               //如果不是接口,报异常
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                
                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)) {
                    //如果不是public修饰,则accessFlags设置为final
                    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 = "";
            }

            {
                List methods = getMethods(interfaces);
                Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
                validateReturnTypes(methods);
                //对异常进行处理
                List[]> exceptions = deduplicateAndGetExceptions(methods);

                Method[] methodsArray = methods.toArray(new Method[methods.size()]);
                Class>[][] exceptionsArray = exceptions.toArray(new Class>[exceptions.size()][]);

                //生成代理的类名格式为:包名+"$Proxy"+随机数字
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;

                //调用native方法生成代理类
                return generateProxy(proxyName, interfaces, loader, methodsArray,
                                     exceptionsArray);
            }
        }

然后调用getMethod(),将equals(),hashcode(),toString()等方法添加进去。然后遍历所有接口的方法,添加到代理类中。最后将这些方法进行排序。

private static List getMethods(Class>[] interfaces) {
        List result = new ArrayList();
        try {
            result.add(Object.class.getMethod("equals", Object.class));
            result.add(Object.class.getMethod("hashCode", EmptyArray.CLASS));
            result.add(Object.class.getMethod("toString", EmptyArray.CLASS));
        } catch (NoSuchMethodException e) {
            throw new AssertionError();
        }

        getMethodsRecursive(interfaces, result);
        return result;
    }
    
private static void getMethodsRecursive(Class>[] interfaces, List methods) {
        for (Class> i : interfaces) {
            getMethodsRecursive(i.getInterfaces(), methods);
            Collections.addAll(methods, i.getDeclaredMethods());
        }
    }

然后回到最初的1处,生成代理类返回。

在2处通过生成的代理类采用反射的方式得到其构造函数。

如果代理类不是public修饰,则cons.setAccessible(true);

在3处调用newInstance生成代理对象。

动态代理源码分析
微信图片_20210318201503.jpg
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。