美文网首页
动态代理原理解析

动态代理原理解析

作者: jxiang112 | 来源:发表于2019-01-31 19:58 被阅读3次

    注:源自于Android

    一、代理模式

    代理模式是java23种设计模式常用的一种设计模式。
    代理模式是客户端不直接调用实际对象,而是通过调用代理对象来间接调用使用实际对象。
    为什么使用代理模式来间接调用使用实际对象,而不是直接使用实际对象呢?这里主要有两方面的考量:

    • 出于安全、封装性的考量,不想直接使用实际对象
    • 使用实际对象比较麻烦
      现实生活中律师、房屋中介其实就是活生生的代理模式
      我们来看下代理模式的关系图:


      image

      java中代理模式分为静态代理和动态代理的不同实现

    1、静态代理的实现:
    public interface Subject {
        void test();
    }
    
    public class RealSubject implements Subject {
        @Override
        public void test() {
            System.out.println("this is RealSubject test");
        }
    }
    
    public class ProxySubject implements Subject {
        Subject mSubject;
    
        public ProxySubject(Subject pSubject){
            mSubject = pSubject;
        }
    
        @Override
        public void test() {
            if(mSubject != null){
                mSubject.test();
            }
        }
    }
    
    public class Client {
        public static void main(String[] args){
            RealSubject realSubject = new RealSubject();
            ProxySubject proxySubject = new ProxySubject(realSubject);
            proxySubject.test();
        }
    }
    

    通过上面的代码我们可以看出静态代理的优缺点:

    • 优点:代理类可以接受一个已经实现了Subject接口的对象,任何实现了Subject接口的对象都可以通过代理类进行代理,实现了通用型
    • 缺点:当接口增删改方法,那么代理类已得要跟着修改;代理类的每个接口对象对应一个委托对象,如果委托对象很多,代理类就会变得异常臃肿
    2、动态代理

    动态代理有别用静态代理,它是通过要代理的类,动态的生成代理类。这样可以避免静态代理中代理类接口过多的问题。
    动态代理的实现方式是借助java.lang.Reflect.Proxy进行反射实现的,其步骤如下:
    a、编写一个委托类接口,对应的静态代理的Subject接口
    b、编写一个委托类接口的实现类,对应的是静态代理的RealSubject
    c、创建动态代理类方法调用处理程序,实现InvocationHandler接口,并重写invoke方法
    d、在测试类中生成动态代理对象
    定义委托对象接口:

    public interface Subject {
        void test();
    }
    

    委托对象接口实现类:

    public class RealSubject implements Subject {
        @Override
        public void test() {
            System.out.print("this is dynamic RealSubject test");
        }
    }
    

    动态代理类方法调用处理程序:

    public class DynamicProxy implements InvocationHandler {
        Object mObj;
        public DynamicProxy(Object pObj){
            mObj = pObj;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            System.out.println("this is Dynamic proxy invode");
            if(mObj != null){
                result = method.invoke(mObj, args);
            }
            return result;
        }
    }
    

    使用动态代理:

    public class Client {
        public static void main(String[] args){
            RealSubject realSubject = new RealSubject();
            DynamicProxy proxy = new DynamicProxy(realSubject);
            Subject subject = (Subject) Proxy.newProxyInstance(
                    realSubject.getClass().getClassLoader(),
                    realSubject.getClass().getInterfaces(),
                    proxy
                    );
            subject.test();
        }
    }
    
    二、动态代理原理

    通过上面动态代理的使用,它看似并没有代理类,那么它是什么进入DynamicProxy的invoke方法实现实际委托对象方法的调用呢?
    下面我们通过源码一步一步解析揭开它什么的面纱:
    动态代理使用了Proxy.newProxyInstance方法动态创建代理类,我们看下newProxyInstance源码:

    /**
    @params loader 用于从动态生成的class字节流中加载创建代理类
    @params interfaces 委托对象实现的接口列表
    @params h 代理类方法调用处理器
    @return 返回动态创建的代理类
    */
    public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            //动态代理类方法调用处理程序即这里的h不能为空
            Objects.requireNonNull(h);
            //委托对象的接口列表
            final Class<?>[] intfs = interfaces.clone();
            //android中移除了安全相关的校验
            // Android-removed: SecurityManager calls
            /*
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }
            */
    
            /*
             * Look up or generate the designated proxy class.
             */
            //动态生成class文件字节流,然后通过loader加载此字节流创建代理类class
            Class<?> cl = getProxyClass0(loader, intfs);
    
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                // Android-removed: SecurityManager / permission checks.
                /*
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
                */
                //获取代理类的类构造对象
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
                //如果class对象不可访问,则修改为可访问
                if (!Modifier.isPublic(cl.getModifiers())) {
                    // BEGIN Android-changed: Excluded AccessController.doPrivileged call.
                    /*
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                    */
    
                    cons.setAccessible(true);
                    // END Android-removed: Excluded AccessController.doPrivileged call.
                }
                // 通过类构造器创建代理实现类并返回
                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);
            }
        }
    

    newProxyInstance动态创建代理类的步骤是:

    • 校验代理类方法调用处理程序h不能为空
    • 动态生成代理类class文件格式字节流
    • 通过loader加载创建代表代理类的class对象
    • 根据代理类的构造器创建代理类
    • 返回动态创建生成的代理类
      怎么生成代理类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);
        }
    

    通过上面的代码告诉我们委托对象能实现的接口数量不能超过65535,就是Short类型的最大值
    我们再看proxyCache.get的实现,其中proxyCache是WeakCache的实现对象:

    //WeakCache.java
    /**
    @params key 此处是类加载器loader
    @params parameter 此处是代理类接口列表
    */
    public V get(K key, P parameter) {
            //此处要求代理类接口不能为空
            Objects.requireNonNull(parameter);
          
            expungeStaleEntries();
            //生成CacheKey对象
            Object cacheKey = CacheKey.valueOf(key, refQueue);
    
            // lazily install the 2nd level valuesMap for the particular cacheKey
            //根据cachekey获取键值对valuesMap, valuesMap的key是接口列表的包装类,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;
                }
            }
    
            // create subKey and retrieve the possible Supplier<V> stored by that
            // subKey from valuesMap
            //根据代理类接口生成的key
            Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
            //动态生成代理类的包装类
            Supplier<V> supplier = valuesMap.get(subKey);
            //生成动态代理类的工厂类
            Factory factory = null;
    
            while (true) {
                //如果动态代理类包装类supplier不为空,则使用supplier 中的工厂类factory加载动态生成的class文件格式的代理类的字节流
                if (supplier != null) {
                    // supplier might be a Factory or a CacheValue<V> instance
                    //此处是factory加载动态生成的class文件格式的代理类的字节流的实现
                    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);
                }
               
                if (supplier == null) {
                   //工厂类的包装类为空,则创建新的包装类supplier 
                    supplier = valuesMap.putIfAbsent(subKey, factory);
                    if (supplier == null) {
                        // successfully installed Factory
                        supplier = factory;
                    }
                    // else retry with winning supplier
                } else {
                   //工厂类的包装类不为空,则替换包装类中的工作累
                    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);
                    }
                }
            }
        }
    

    由上面的代码,大概知道通过map来存储动态生成的代理类,其中key是接口的包装类,value是动态代理类的包装类。

    • key的生成是通过subKeyFactory,subKeyFactory是KeyFactory的实现类,其实现很简单,只是对代理类接口进行包装:
    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 final int hash;
    
            Key1(Class<?> intf) {
                super(intf);
                this.hash = intf.hashCode();
            }
    
            @Override
            public int hashCode() {
                return hash;
            }
    
            @Override
            public boolean equals(Object obj) {
                Class<?> intf;
                return this == obj ||
                       obj != null &&
                       obj.getClass() == Key1.class &&
                       (intf = get()) != null &&
                       intf == ((Key1) obj).get();
            }
        }
    

    其他key1、keyx不展开说明

    • value是生成动态代理类的包装类,此包装类是实现了Supplier接口的Factory类,通过Factory的get方法动态生成代理类:
    @Override
            public synchronized V get() { // serialize access
                // re-check
                //从map中获取已经生成的动态代理类的包装类
                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 {
                    //通过valueFactory的apply方法生成动态代理类
                    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);
    
                // try replacing us with CacheValue (this should always succeed)
                if (valuesMap.replace(subKey, this, cacheValue)) {
                    // put also in 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;
            }
    

    这里核心的实现是valueFactory的apply方法,valueFactory是ProxyClassFactory的实现类,我们来看下ProxyClassFactory的apply方法,看其是怎么实现生成动态代理类的:

    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    
                Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
                //获取代理类接口的class对象,并校验是否是接口,如果不是则抛出错误
                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;
    
                /*
                 * Record the package of a non-public proxy interface so that the
                 * proxy class will be defined in the same package.  Verify that
                 * all non-public proxy interfaces are in the same package.
                 */
                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;
                    //根据类名、接口、类加载器、方法列表、异常列表,按照class文件格式先生成字节流,再生成动态代理类
                    return generateProxy(proxyName, interfaces, loader, methodsArray,
                                         exceptionsArray);
                }
            }
    
    //native方法,其实现原理是根据类名、接口、类加载器、方法列表、异常列表,按照class文件格式先生成字节流,再生成动态代理类
    @FastNative
    private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
                                                     ClassLoader loader, Method[] methods,
                                                     Class<?>[][] exceptions);
    

    按照这样的流程,我们可以总结动态代理的原理如下:
    1、根据代理类接口先得到代理类的类全限名、方法列表、异常列表
    2、根据步骤1中的类全限名、方法列表、异常列表、接口列表生成class文件格式的字节流,其中方法的实现会最终调用InvoationHanlder的invoke方法
    3、使用类加载器加载步骤2中的字节流,创建生成动态代理类对象
    4、使用步骤3中创建生成的代理类对象

    相关文章

      网友评论

          本文标题:动态代理原理解析

          本文链接:https://www.haomeiwen.com/subject/nrhcsqtx.html