zoukankan      html  css  js  c++  java
  • jdk动态代理实现

    动态代理示例:

    public class VectorProxy implements InvocationHandler {
      private Object proxyObject;
      //执行方法时候调用
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object o = method.invoke(proxyObject,args);
        System.out.println("after");
        return o;
      }
      public VectorProxy(Object proxyObject) {
        this.proxyObject = proxyObject;
      }
      public Object bind(){
        return Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),proxyObject.getClass().getInterfaces(),this);
      }
      public static void main(String[] args) throws Throwable {
        Vector vector = new Vector();
        VectorProxy vectorProxy = new VectorProxy(vector);
        List v= (List) vectorProxy.bind();
        v.add("123");
    //    vectorProxy.invoke(null,vector.getClass().getMethod("add",Object.class),new Object[]{2});
        System.out.println(vector.size());
      }
    }
    


    动态代理对象是如何生成的?invoke方法又是何时执行的?,阅读静态工厂方法的代码:

    @CallerSensitive
        public static Object newProxyInstance(ClassLoader loader,//被代理对象的类加载器
                                              Class<?>[] interfaces,//被代理对象实现的接口
                                              InvocationHandler h)//代理对象handler
            throws IllegalArgumentException
        {
            if (h == null) {
                throw new NullPointerException();
            }
            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.
             *可见,生成的代理对象包含一个参数类型是InvocationHandler的构造方法,执行方法时,就可以调用这个InvocationHandler的invoke方法,从而实现
             *动态代理
             */
            try {
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
                if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
                    // create proxy instance with doPrivilege as the proxy class may
                    // implement non-public interfaces that requires a special permission
                    return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        public Object run() {
                            return newInstance(cons, ih);
                        }
                    });
                } else {
                    return newInstance(cons, ih);
                }
            } catch (NoSuchMethodException e) {
                throw new InternalError(e.toString());
            }
        }

    getProxyClass0(loader, intfs)方法实现如下:  

     /**
         * Generate a proxy class.  Must call the checkProxyAccess method
         * to perform permission checks before calling this.
         */
        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,这个是动态代理对象缓存,代码如下.这段代码有点麻烦,似乎是当对象不存在时创建新对象,不过最重要的是subKeyFactory的apply()方法

     public V get(K key, P parameter) {
            Objects.requireNonNull(parameter);
            expungeStaleEntries();
            Object cacheKey = CacheKey.valueOf(key, refQueue);
            // lazily install the 2nd level valuesMap for the particular cacheKey
            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));
            Supplier<V> supplier = valuesMap.get(subKey);
            Factory factory = null;
            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);
                }
                if (supplier == null) {
                    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);
                    }
                }
            }
        }

    这个方法重要的是
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

    apply方法是用来生成字节码数组的:这里可以很清楚地知道生成的包名,类名是啥

     /**
         * A factory function that generates, defines and returns the proxy class given
         * the ClassLoader and array of interfaces.
         */
        private static final class ProxyClassFactory
            implements BiFunction<ClassLoader, Class<?>[], Class<?>>
        {
            // prefix for all proxy class names
            private static final String proxyClassNamePrefix = "$Proxy";
            // next number to use for generation of unique proxy class names
            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) {
                    /*
                     * 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
                /*
                 * 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)) {
                        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 com.sun.proxy package
                    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
                }
                /*
                 * Choose a name for the proxy class to generate.
                 */
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
                /*
                 * Generate the specified proxy class.
                 */
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces);
                try {
                    return defineClass0(loader, proxyName,
                                        proxyClassFile, 0, proxyClassFile.length);
                } catch (ClassFormatError e) {
                    /*
                     * A ClassFormatError here means that (barring bugs in the
                     * proxy class generation code) there was some other
                     * invalid aspect of the arguments supplied to the proxy
                     * class creation (such as virtual machine limitations
                     * exceeded).
                     */
                    throw new IllegalArgumentException(e.toString());
                }
            }
        }

    生成字节码数组是通过如下代码:
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
        proxyName, interfaces);
    这个方法有些复杂,就不做研究了
    可以写一个程序,单独测试这个方法,让其生成字节码文件,打开class文件就知道invoke方法是如何调用的:

    public class ProxyGeneratorUtils {
      /**
       * 把代理类的字节码写到硬盘上
       * @param path 保存路径
       */
      public static void writeProxyClassToHardDisk(String path) {
        // 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了
        // System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);
        // 第二种方法
        // 获取代理类的字节码
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", Vector.class.getInterfaces());
        FileOutputStream out = null;
        try {
          out = new FileOutputStream(path);
          out.write(classFile);
          out.flush();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          try {
            out.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
      @Test
      public void testGenerateProxyClass() {
        ProxyGeneratorUtils.writeProxyClassToHardDisk("/f/classes/$Proxy11.class");
      }
    }

    打开生成的文件,可以观察到: 代理类实现了相关的接口,并重写了相关方法,在调用时实际是调用了InvocationHandler的invode方法

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    import java.io.Serializable;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ListIterator;
    import java.util.RandomAccess;
    public final class $Proxy11 extends Proxy implements List, RandomAccess, Cloneable, Serializable {
      private static Method m14;
      private static Method m13;
      private static Method m19;
      private static Method m2;
      private static Method m25;
      private static Method m9;
      private static Method m5;
      private static Method m16;
      private static Method m3;
      private static Method m17;
      private static Method m18;
      private static Method m24;
      private static Method m10;
      private static Method m8;
      private static Method m20;
      private static Method m21;
      private static Method m4;
      private static Method m12;
      private static Method m1;
      private static Method m15;
      private static Method m23;
      private static Method m7;
      private static Method m22;
      private static Method m11;
      private static Method m0;
      private static Method m6;
      public $Proxy11(InvocationHandler var1) throws  {
        super(var1);
      }
      public final List subList(int var1, int var2) throws  {
        try {
          return (List)super.h.invoke(this, m14, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)});
        } catch (RuntimeException | Error var4) {
          throw var4;
        } catch (Throwable var5) {
          throw new UndeclaredThrowableException(var5);
        }
      }
      public final int size() throws  {
        try {
          return ((Integer)super.h.invoke(this, m13, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
          throw var2;
        } catch (Throwable var3) {
          throw new UndeclaredThrowableException(var3);
        }
      }
      public final Iterator iterator() throws  {
        try {
          return (Iterator)super.h.invoke(this, m19, (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 boolean retainAll(Collection var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m25, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final void clear() throws  {
        try {
          super.h.invoke(this, m9, (Object[])null);
        } catch (RuntimeException | Error var2) {
          throw var2;
        } catch (Throwable var3) {
          throw new UndeclaredThrowableException(var3);
        }
      }
      public final boolean remove(Object var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m5, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final Object[] toArray(Object[] var1) throws  {
        try {
          return (Object[])super.h.invoke(this, m16, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final boolean add(Object var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m3, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final boolean addAll(int var1, Collection var2) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m17, new Object[]{Integer.valueOf(var1), var2})).booleanValue();
        } catch (RuntimeException | Error var4) {
          throw var4;
        } catch (Throwable var5) {
          throw new UndeclaredThrowableException(var5);
        }
      }
      public final boolean addAll(Collection var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m18, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final boolean removeAll(Collection var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m24, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final boolean contains(Object var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m10, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final int indexOf(Object var1) throws  {
        try {
          return ((Integer)super.h.invoke(this, m8, new Object[]{var1})).intValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final Object set(int var1, Object var2) throws  {
        try {
          return (Object)super.h.invoke(this, m20, new Object[]{Integer.valueOf(var1), var2});
        } catch (RuntimeException | Error var4) {
          throw var4;
        } catch (Throwable var5) {
          throw new UndeclaredThrowableException(var5);
        }
      }
      public final boolean containsAll(Collection var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m21, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final void add(int var1, Object var2) throws  {
        try {
          super.h.invoke(this, m4, new Object[]{Integer.valueOf(var1), var2});
        } catch (RuntimeException | Error var4) {
          throw var4;
        } catch (Throwable var5) {
          throw new UndeclaredThrowableException(var5);
        }
      }
      public final int lastIndexOf(Object var1) throws  {
        try {
          return ((Integer)super.h.invoke(this, m12, new Object[]{var1})).intValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final boolean equals(Object var1) throws  {
        try {
          return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final Object[] toArray() throws  {
        try {
          return (Object[])super.h.invoke(this, m15, (Object[])null);
        } catch (RuntimeException | Error var2) {
          throw var2;
        } catch (Throwable var3) {
          throw new UndeclaredThrowableException(var3);
        }
      }
      public final ListIterator listIterator(int var1) throws  {
        try {
          return (ListIterator)super.h.invoke(this, m23, new Object[]{Integer.valueOf(var1)});
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final Object get(int var1) throws  {
        try {
          return (Object)super.h.invoke(this, m7, new Object[]{Integer.valueOf(var1)});
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      public final ListIterator listIterator() throws  {
        try {
          return (ListIterator)super.h.invoke(this, m22, (Object[])null);
        } catch (RuntimeException | Error var2) {
          throw var2;
        } catch (Throwable var3) {
          throw new UndeclaredThrowableException(var3);
        }
      }
      public final boolean isEmpty() throws  {
        try {
          return ((Boolean)super.h.invoke(this, m11, (Object[])null)).booleanValue();
        } 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)).intValue();
        } catch (RuntimeException | Error var2) {
          throw var2;
        } catch (Throwable var3) {
          throw new UndeclaredThrowableException(var3);
        }
      }
      public final Object remove(int var1) throws  {
        try {
          return (Object)super.h.invoke(this, m6, new Object[]{Integer.valueOf(var1)});
        } catch (RuntimeException | Error var3) {
          throw var3;
        } catch (Throwable var4) {
          throw new UndeclaredThrowableException(var4);
        }
      }
      static {
        try {
          m14 = Class.forName("java.util.List").getMethod("subList", new Class[]{Integer.TYPE, Integer.TYPE});
          m13 = Class.forName("java.util.List").getMethod("size", new Class[0]);
          m19 = Class.forName("java.util.List").getMethod("iterator", new Class[0]);
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m25 = Class.forName("java.util.List").getMethod("retainAll", new Class[]{Class.forName("java.util.Collection")});
          m9 = Class.forName("java.util.List").getMethod("clear", new Class[0]);
          m5 = Class.forName("java.util.List").getMethod("remove", new Class[]{Class.forName("java.lang.Object")});
          m16 = Class.forName("java.util.List").getMethod("toArray", new Class[]{Class.forName("[Ljava.lang.Object;")});
          m3 = Class.forName("java.util.List").getMethod("add", new Class[]{Class.forName("java.lang.Object")});
          m17 = Class.forName("java.util.List").getMethod("addAll", new Class[]{Integer.TYPE, Class.forName("java.util.Collection")});
          m18 = Class.forName("java.util.List").getMethod("addAll", new Class[]{Class.forName("java.util.Collection")});
          m24 = Class.forName("java.util.List").getMethod("removeAll", new Class[]{Class.forName("java.util.Collection")});
          m10 = Class.forName("java.util.List").getMethod("contains", new Class[]{Class.forName("java.lang.Object")});
          m8 = Class.forName("java.util.List").getMethod("indexOf", new Class[]{Class.forName("java.lang.Object")});
          m20 = Class.forName("java.util.List").getMethod("set", new Class[]{Integer.TYPE, Class.forName("java.lang.Object")});
          m21 = Class.forName("java.util.List").getMethod("containsAll", new Class[]{Class.forName("java.util.Collection")});
          m4 = Class.forName("java.util.List").getMethod("add", new Class[]{Integer.TYPE, Class.forName("java.lang.Object")});
          m12 = Class.forName("java.util.List").getMethod("lastIndexOf", new Class[]{Class.forName("java.lang.Object")});
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
          m15 = Class.forName("java.util.List").getMethod("toArray", new Class[0]);
          m23 = Class.forName("java.util.List").getMethod("listIterator", new Class[]{Integer.TYPE});
          m7 = Class.forName("java.util.List").getMethod("get", new Class[]{Integer.TYPE});
          m22 = Class.forName("java.util.List").getMethod("listIterator", new Class[0]);
          m11 = Class.forName("java.util.List").getMethod("isEmpty", new Class[0]);
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          m6 = Class.forName("java.util.List").getMethod("remove", new Class[]{Integer.TYPE});
        } catch (NoSuchMethodException var2) {
          throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
          throw new NoClassDefFoundError(var3.getMessage());
        }
      }
    }
    总结

       JDK实现动态代理的过程如下:

        克隆传入的接口Class数组(通过clone()方法)

        查找或者生成实现了接口数组中所有接口的动态代理类的Class

        利用动态代理类的Class获取Constructor对象,利用我们传入的InvocationHandler实现类对象作为输入参数,生成动态代理类的对象动态代理类对象的性质:

        实现了传入的接口Class数组中所有的接口

        这些接口中如果含有非public的接口,非public接口必须在同一个包下面,而且代理类也必须和他们在同一包下,要不代理类必然访问

    不了部分接口

        父类(Proxy)有一个InvocationHandler的成员变量,它的值是我们在Proxy.newInstance()方法中传入的,子类的所有方法都是围绕InvocationHandler进行.

  • 相关阅读:
    [Swift]数学库函数math.h | math.h -- mathematical library function
    [Swift]LeetCode492. 构造矩形 | Construct the Rectangle
    FansMail:邮件发送标准API与技术实现(Java)
    FansMail:邮件发送标准API与技术实现(Java)
    大话世界格局:春秋五霸与战国七雄
    大话世界格局:春秋五霸与战国七雄
    大家好,我是FansUnion,雷文
    大家好,我是FansUnion,雷文
    2013年总结(2)-财务收入与支出
    2013年总结(2)-财务收入与支出
  • 原文地址:https://www.cnblogs.com/xingxingge/p/10311439.html
Copyright © 2011-2022 走看看