zoukankan      html  css  js  c++  java
  • Java中代理

    普通代理(最简单的代理)

    需要有两个实现同一个接口的类,一个是被代理的类,一个是代理类

    被代理类中我们按照自己想实现的功能重写接口中的方法

    代理类中因为需要代理被代理类,所以在代理类中需要有个被代理类的实例,这样在重写接口中的方法的时候,直接调用代理类中的实例中对应的方法直接实现代理功能

    具体代码的实现

    interface Interface{
        void dosomething();
        void dosomethingelse(String args);
    }
    class RealObject implements Interface{         //被代理的类
    
        @Override
        public void dosomething() {
            System.out.println("do something!!!");
        }
    
        @Override
        public void dosomethingelse(String args) {
            System.out.println("do something else:"+args);
        }
    }
    class CommonProxy implements Interface{         //代理类
        private Interface proxied;               //这个接口应该是指向被代理对象的实例
    
        public CommonProxy(Interface proxied) {
            this.proxied = proxied;
        }
    
        @Override
        public void dosomething() {
           proxied.dosomething();        //直接调用被代理对象中的方法实现代理功能    
        }
    
        @Override
        public void dosomethingelse(String args) {
            proxied.dosomethingelse(args);
        }
    }
    public class SimpleProxyDemo{
        public  static  void consumer(Interface inter){
            inter.dosomethingelse("booo");
            inter.dosomething();
        }
        
        public static void main(String[] args) {
            consumer(new CommonProxy(new RealObject()));
        }
    }

    动态代理技术

    上面的代理对象都是我们手动写的,Java动态代理技术可以实现动态的创建代理对象,并且动态的处理对代理方法的调用

    简单的代码实现(有一部分使用的是上面的接口和实现类)

    class DynamicProxyHandler  implements InvocationHandler {
    Object proxied;

    public DynamicProxyHandler(Object proxied) {
    this.proxied = proxied;
    }

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

    public class DynamicProxyDemo{
    public static void main(String[] args) {
    RealObject realObject=new RealObject();
    Interface proxy = (Interface) Proxy
    .newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(new RealObject()));
    proxy.dosomethingelse("shei");
    proxy.dosomething();
    }
    }

    使用步骤:

    定义一个实现InvocationHandler接口的调用处理器,重写里面的invoke方法

    直接使用Proxy中的静态方法创建代理类,创建的过程中需要一个类加载器,一个被代理的接口,还有一个上面定义的调用处理器。

    注意最后将生成的代理对象转换成我们需要的被代理类实现的接口,在上面就是Interface接口,注意这里的Interface是首字母大写,不是Java中的关键字。

    动态代理的原理

    Proxy.newProxyInstance()函数

     public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            Objects.requireNonNull(h);        //首先判断传递的调用处理器是不是空,否则就抛出空指针异常
    
            final Class<?>[] intfs = interfaces.clone();      //使用clone()函数实现初始化接口的Class对象数组。
            final SecurityManager sm = System.getSecurityManager();      
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }
    
            /*
             * Look up or generate the designated proxy class.
             */
            Class<?> cl = getProxyClass0(loader, intfs);         //生成代理对象的Class对象实例。
    
    /*
             * 借助调用处理器生成对应的代理类
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
    
                final Constructor<?> cons = cl.getConstructor(constructorParams);    //获得代理类的构造函数
                final InvocationHandler ih = h;
                if (!Modifier.isPublic(cl.getModifiers())) {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                }
                return cons.newInstance(new Object[]{h}); //使用代理类的构造函数和InvocationHandler实例化一个代理对象,最后返回代理对象
            } 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);
            }
        }

    下面函数是二级缓存类WeakCache类中的get()函数,其实例对象就是cacheProxyClass,下面函数中如果根据提供的类加载器和接口数组能在缓存中找到代理类就直接返回该代理类,否则会调用ProxyClassFactory工厂去生成代理类。这里用到的缓存是二级缓存,它的一级缓存key是根据类加载器生成的,二级缓存key是根据接口数组生成的。

    代理类Class对象的生成(上面黄色的部分)最终会定位到WeakCache类的实例proxyClassCache中的get()函数。ProxyClassCache对象有两个变量,KeyFactory和ProxyClassFactory,前者实现生成二级缓存的subkey,根据subkey在Concurrentmap中取出对应的factory(代码中使用父接口Supplier引用supplier指向),由supplier的get()函数得到对应的value(代理类class对象)。

    public V get(K key, P parameter) {
            Objects.requireNonNull(parameter);
    
            expungeStaleEntries();
    
            Object cacheKey = CacheKey.valueOf(key, refQueue);
    
            // 根据由类加载器生成的一级缓存的key向缓存中取对应的concurrentmap值
            ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
            if (valuesMap == null) {                               //如果没有valuesmap就创建一对放进去,
                               //只不过里面的concurrentmap还没有什么东西(二次缓存的key和工厂)
    ConcurrentMap
    <Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // 运行到这里,生成二次缓存的key(使用classloader和interface生成), // 取出里面对应的代理类supplier Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); Supplier<V> supplier = valuesMap.get(subKey);//注意缓存的只是Supplier指向的工厂,没有缓存代理类Class对象 Factory factory = null; while (true) { if (supplier != null) { // supplier可能是个工厂也可能是缓存,由他提供对应的代理类Class对象 V value = supplier.get(); //注意这一步是生成代理Class对象的关键,
                                  //由缓存或者新建的supplier创建代理的Class对象
    if (value != null) { return value; } } // 否则没有supplier,由下面的语句生成对应的supplier // 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); //这就是supplier    } if (supplier == null) { supplier = valuesMap.putIfAbsent(subKey, factory); //将生成的factory放进缓存,方便下次使用。 if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else {                              //supplier只是Factory的父接口 if (valuesMap.replace(subKey, supplier, factory)) { //有supplier但是经过get()方法得到的是空,
                                              //及所以这里使用新的factory替换之前的supplier
    // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // 否则就使用现在的supplier重试 supplier = valuesMap.get(subKey); } } } }

    Factory类中的get()函数(上面的黄色部分),其实现了supplier接口重写了里面的get()方法

     public synchronized V get() { // serialize access
                // 根据二级的key查询得到factory对象,检查拿到的和现在的相比是否一致,
            //factory中有点像循环引用,因为factory对象中的ConCurrentMap中含有当前对象的引用
    Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { // 检查缓存是否一致,不一致就设为null,返回上一个函数继续生成对应的Factory对象 return null; } // else still us (supplier == this) // create new value V value = null; try { value = Objects.requireNonNull(valueFactory.apply(key, parameter)); //生成对应的代理class对象,
                                            //valueFactory就是上面ProxyClassCache的实现类
    }
    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); //CacheValue继承自Supplier,
                                        //同样也含有get()(是父类reference中的函数)函数返回对应的值。
    // put into reverseMap reverseMap.put(cacheValue, Boolean.TRUE); // try replacing us with CacheValue (this should always succeed) if (!valuesMap.replace(subKey, this, cacheValue)) { throw new AssertionError("Should not reach here"); } // successfully replaced us with new CacheValue -> return the value // wrapped by it return value; } }

    上面黄色部分最终会执行下面proxyclassfactory中的apply()函数

        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) {
                    /*
                     * 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");
                    }
                    /*
                     * 判断是不是代表一个接口
                     */
                    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) {
                    // 如果没有非公有的interface就使用sun公司自己默认的包
                    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
                }
    
                /*
                 * 为代理类生成名字   类似  $proxy0
                 */
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
    
                /*
                 * 由proxygenerator生成对应的Class类的字节形式,使用我们给的类加载器加载对应的类。
                 */
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
    proxyName, interfaces, accessFlags);
    try {
                    return defineClass0(loader, proxyName,     //native 方法
                                        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());
                }
            }
        }

    最后我们看看上面的红色部分,ProxyGenerator类的generatorProxyClass()函数

    public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
            ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
            final byte[] var4 = var3.generateClassFile();
    if (saveGeneratedFiles) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        try {
                            int var1 = var0.lastIndexOf(46);//46在ASCII码中就是  “.”
                            Path var2;
                            if (var1 > 0) {
                                Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                                Files.createDirectories(var3);            //和上面一起用来创建代理类的存放目录
                                var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");//这个就是代理类的名字 $proxy0.class
                            } else {
                                var2 = Paths.get(var0 + ".class");//var2是代理类的全路径名
                            }
    
                            Files.write(var2, var4, new OpenOption[0]);//最后写进对应的文件。
                            return null;
                        } catch (IOException var4x) {
                            throw new InternalError("I/O exception saving generated file: " + var4x);
                        }
                    }
                });
            }
    
            return var4;
        }

     上面的黄色部分里面使用了很多反射生成对应的byte数组,里面写的就应该是class文件的内容,

    动态代理中最重要的就是Proxy类,里面含有大量的静态变量和静态函数

    静态变量:WeakCache类型的实例  proxyClassCache

         InnovationHandler实例h

    所含的内部类:

         内部类keyFactory(在二级缓存中用于生成二级缓存的subkey)

         内部类ProxyClassFactory(和上面一个内部类一起实例化上面的代理Class类的二级缓存WeakCache,在缓存中这个用于获得或者生成代理类Class对象)

         Factory(实例存储在二级缓存中,最终调用它的get()函数返回对应的代理类Class文件)

    静态函数:

          newProxyInstance(classloader,classes[],InvocationHandler),(这个函数的会调用下面的函数,返回代理类Class对象实例,最终使用反射生成代理类实例)

          getproxyclass0(classloader,classes)(这个函数会直接调用WeakCache的get()函数查询proxyClassCache缓存)

          根据classloader生成一级缓存的key,取出concurrentmap,在根据classloader和interfaces使用keyFactory中apply函数生成subkey,根据subkey取出对应的supplier,有下面两 种情况,

          一种:supplier是一个缓存,这时候supplier指向的是一个CacheValue的对象,调用get()函数是其父类weakreference的父类reference中的get()函数,函数返回缓存中的值

          另一种:当前supplier中没有值,这时候使用ProxyClassFactory中的apply()函数生成对应的代理类的Class对象,并且存进CacheValue中。

          

              

    
    
  • 相关阅读:
    jdk.exe转zip免安装
    jdk全版本下载链接
    Cesium primitive绘制折线和多边形
    sql调优的几种方式
    maven操作
    如何设计高并发系统?
    用友华表cell的程序发布
    OpenCV异常问题(一)
    js jquery window 高 宽
    sql中游标的使用一
  • 原文地址:https://www.cnblogs.com/feixiangdecainiao/p/10646026.html
Copyright © 2011-2022 走看看