Bootstrap

Android动态代理源码分析

前言

前面我们简单介绍了代理模式的使用Android设计模式详解之代理模式,我们也明白了动态代理模式的重要性,那动态代理究竟是如何实现将方法交给InvocationHandler.invoke执行的呢?本文就从源码的角度一步步去探究这个问题;

源码分析

从前面一篇文章我们知道动态代理是通过调用 Proxy.newProxyInstance()方法来实现的,我们就从这个方法入手
Proxy.newProxyInstance()方法:

	//constructorParams成员变量
    private static final Class<?>[] constructorParams =
        { InvocationHandler.class };

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {	
    	//先检查传入的InvocationHandler是否为空,为空则直接抛空指针
        Objects.requireNonNull(h);
		//克隆一份代理接口,并通过传入的classLoader去获取一个代理class
        final Class<?>[] intfs = interfaces.clone();
        Class<?> cl = getProxyClass0(loader, intfs);

        try {
   			//获取代理class的带有InvocationHandler参数的构造函数
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            //如果构造函数是私有的,反射设置可访问
            if (!Modifier.isPublic(cl.getModifiers())) {
                cons.setAccessible(true);  
            }
            //通过反射生成代理对象
            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);
        }
    }

整体看下来还是比较轻松的,主要就是通过传入的类加载器代理接口以及InvocationHandler调用反射去创建一个代理类的对象实例;

这里我们再重点分析下代理类的创建流程, Class<?> cl = getProxyClass0(loader, intfs);这段代码

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

    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
      	//很明显这里做了缓存处理
        return proxyClassCache.get(loader, interfaces);
    }

可以看到代理类最终是交给ProxyClassFactory工厂类创建的,我们就重点看下ProxyClassFactory

    /**
     * 一个工厂函数,在给定ClassLoader和接口数组的情况下生成、定义和返回代理类。
     */
    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) {
                Class<?> interfaceClass = null;
                try {
                	//反射获取代理接口对应的class
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                	//通过classLoader加载的class与原代理接口不一致则抛异常
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
             	//反射获取代理接口对应的class不是一个接口则抛异常
                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;     //代理类包名
            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) {
                proxyPkg = "";
            }

            {
               //获取接口中的所有方法
                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()][]);
				//代理类名依次递增
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
                //生成代码类
                return generateProxy(proxyName, interfaces, loader, methodsArray,
                                     exceptionsArray);
            }
        }
    }

代理类的创建工作交给ProxyClassFactory工厂来完成,ProxyClassFactory.apply方法会遍历所有的代理接口,并做校验、方法排序等工作,最终会调用generateProxy方法来生成代理类,而generateProxy方法是一个native方法!!!

    private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
                                                 ClassLoader loader, Method[] methods,
                                                 Class<?>[][] exceptions);

经过上面的步骤,就通过调用 Proxy.newProxyInstance()方法生成了代理类,并创建了代理类的实例对象返回;

那这个创建的代理类长什么样呢?为什么通过代理类的对象调用代理接口方法就可以执行到InvocationHandler.invoke方法中呢?

我们在调用 Proxy.newProxyInstance()方法前,修改下系统属性如下:

 //修改属性设置保存生成的proxy文件
        System.getProperties().setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true")

这样我们就可以看到生成的代理对象
生成的代理对象

我这里还是前面的租客租房例子,生成的代理对象如下:

package com.sun.proxy;

import com.crystal.essayjoker.pattern.proxy.dynamic.IRental;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements IRental {
    private static Method m1;
    private static Method m3;
    private static Method m4;
    private static Method m2;
    private static Method m0;

    public $Proxy0(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 void renting() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

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

    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("com.crystal.essayjoker.pattern.proxy.dynamic.IRental").getMethod("renting");
            m4 = Class.forName("com.crystal.essayjoker.pattern.proxy.dynamic.IRental").getMethod("rentingOut");
            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());
        }
    }
}

可以看到调用proxy的代理方法最终还是通过反射调用传入的InvocationHandler的invoke方法,至此谜题解开;

总结

动态代理的实现原理:
调用 Proxy.newProxyInstance()方法会通过反射带有InvocationHandler参数的构造函数生成代理类,并返回代理类的实例,当调用代理类的方法时,又会通过反射执行InvocationHandler对应的invoke方法,从而实现动态代理这套机制;

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

;