美文网首页
Java-反射-动态代理

Java-反射-动态代理

作者: 写代码的阿毛 | 来源:发表于2020-03-02 16:39 被阅读0次

    概述

    • Proxy 提供静态方法来创建动态代理类和动态代理对象;
    • 源码基于 Android-SDK-29 中的 JDK;

    动态代理类

    • 动态代理类的父类是 Proxy,并且实现了动态创建时指定的接口;类名不是明确的,以 $Proxy 开头;
    • 如果代理接口都是 public ,那么动态代理类是 public final 的,不是 abstract;如果代理接口中有任意一个是 not public ,那么动态代理类是 not public final 的,不是 abstract ,动态代理类所在的包和 not public 代理接口所在的包一致;
    • 每个动态代理类有一个 public 的构造函数,该构造函数只有一个 InvocationHandler 类型的参数;
    • 如果一个具有相同排列的代理接口的动态代理类已经被一个 ClassLoader 定义了,就不会重复生成新的动态代理类

    动态代理对象

    • 动态代理对象是动态代理类的实例,动态代理类的构造方法是只有一个 InvocationHandler 类型的参数;
    • 动态代理对象的所有方法调用,包括 hashCode equals toString ,以及代理接口的方法调用,都是转发给关联的 InvocationHandler 对象实现的;

    源码

    • InvocationHandler
      protected InvocationHandler h;
      
      protected Proxy(InvocationHandler h) {
            Objects.requireNonNull(h);
            this.h = h;
        }
      
      public interface InvocationHandler {
      
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
      }
      
      • 每个动态代理对象都绑定一个 InvocationHandler 对象,动态代理对象的所有方法调用,都要转发给 InvocationHandler#invoke
    • getProxyClass
      private static Class<?> getProxyClass0(ClassLoader loader,
                                               Class<?>... interfaces) {
            if (interfaces.length > 65535) {
                throw new IllegalArgumentException("interface limit exceeded");
            }
            return proxyClassCache.get(loader, interfaces);
        }
      
      • 如果指定的 ClassLoader 已经定义了相同排列的代理接口的动态代理类,那么直接返回;否则,动态生成类;
    • newProxyInstance
      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);
      
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                //动态代理类的构造函数
                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);
            }
        }
      
      • 先生成对应的动态代理类,再通过构造函数生成动态代理对象;
    • isProxyClass
      public static boolean isProxyClass(Class<?> cl) {
            return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
        }
      
      • 判断是否是动态代理类;

    相关文章

      网友评论

          本文标题:Java-反射-动态代理

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