zoukankan      html  css  js  c++  java
  • java之静态代理和动态代理

    我们以几个问题,来开始我们今天的学习,如果下面几个问题,你都能说出个一二,那么恭喜你,你已经掌握了这方面的知识。
    1,什么是代理模式?
    2,Java中,静态代理与动态代理的区别?
    3,Spring使用的是JDK的动态代理,还是CGLIB的动态代理?
    4,JDK的动态代理的实现原理?
    5,JDK的动态代理与CGLIB的动态代理的实现上,有何不同?
    6,你知道的,还有其他动态代理技术吗?请简述实现原理。

    OK,言归正传。

    Java的代理模式分为:静态代理和动态代理。首先我们需要搞清楚,什么是代理模式?注意,我们这里说的是JDK的代理模式。代理模式中,代
    理类和委托类具有相同的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间
    通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,
    来提供特定的服务。
        说白了,JDK的代理模式,提供了另一种生成对象的方式。从程序结构上来说,JDK的代理模式,把代理类作为对象,代理代理类完成基本的功能,
    并且增加了其他行为,我们可以在代理类执行之前(后),插入一段代码,完成其他的附加功能。我们可以把这种模式,看做是对生成对象的一种控制,
    或者说是一种管理。Spring管理bean使用的就是动态代理。
        代理模式是23种设计模式之一,我们来回顾一下23种设计模式:
    Factory(工厂模式)  
    Builder(建造模式)  
    Factory Method(工厂方法模式)  
    Prototype(原始模型模式)  
    Singleton(单例模式)  
    Facade(门面模式)  
    Adapter(适配器模式)  
    Bridge(桥梁模式)  
    Composite(合成模式)  
    Decorator(装饰模式)  
    Flyweight(享元模式)  
    Proxy(代理模式)  
    Command(命令模式)  
    Interpreter(解释器模式)  
    Visitor(访问者模式)  
    Iterator(迭代子模式)  
    Mediator(调停者模式)  
    Memento(备忘录模式)  
    Observer(观察者模式)  
    State(状态模式)  
    Strategy(策略模式)  
    Template Method(模板方法模式)  
    Chain Of Responsibleity(责任链模式)

        按照代理的创建时期,代理类可以分为:静态代理和动态代理。静态代理指的是,由程序员创建或特定工具自动生成源代码,再对其进行编译。
    在程序运行前,代理类的.class文件就已经存在了。动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。
        只看概念,比较抽象,我们下面来看一下代码示例。我们先来看一下静态代理的组成要素:
    * 一个接口
    * 一个接口实现类

    * 一个代理类,也实现了接口,是增强版的实现类

    /** 
     * @description 代理模式 之 静态代理 -- StaticProxyInterface接口 
     * @description 一个接口 
     */  
    public interface StaticProxyInterface {  
        public void queryInfo();  
    }  
    

      

    /** 
     * @description 代理模式 之 静态代理 -- StaticProxyImpl实现类  
     * @description StaticProxyImpl,在代理模式中,叫做委托类,包含业务逻辑 
     * @description 一个接口实现类 
     */  
    public class StaticProxyImpl implements StaticProxyInterface{  
        public void queryInfo() {  
            System.out.println("代理模式 之 静态代理 -- StaticProxyImpl实现类   查看信息...");  
        }  
    } 
    

      

    /** 
     * @description 代理模式 之 静态代理 -- StaticProxy代理类 
     * @description StaticProxy,在代理模式中,叫做代理类,增强StaticProxyImpl实现类  
     * @description 一个代理类,也实现了接口,是增强版的实现类 
     */  
    public class StaticProxy  implements StaticProxyInterface{  
      
        private StaticProxyImpl staticProxyImpl;  
        public StaticProxy(StaticProxyImpl staticProxyImpl){  
            this.staticProxyImpl = staticProxyImpl;  
        }  
        public void queryInfo() {  
            // 事务处理之前,可以执行一段代码  
            System.out.println("事务处理之前...");  
            // 调用委托类的方法  
            staticProxyImpl.queryInfo();  
            // 事务处理之后,可以执行一段代码  
            System.out.println("事务处理之后...");  
        }  
    }  
    

      

    /** 
     * @description 代理模式 之 静态代理 
     * @description 测试类StaticProxyTest 
     * @description 什么是静态代理:静态代理指的是,由程序员创建或特定工具自动生成源代码,再对其进行编译。 
     * 在程序运行前,代理类的.class文件就已经存在了。 
     * @description 静态代理组成要素: 
     * 1,一个接口 
     * 2,一个接口实现类 
     * 3,一个代理类,也实现接口,是增强版的接口实现类 
     */  
    public class StaticProxyTest {  
        public static void main(String[] args){  
            StaticProxyImpl staticProxyImpl = new StaticProxyImpl();  
            StaticProxy staticProxy = new StaticProxy(staticProxyImpl);  
            staticProxy.queryInfo();  
        }  
        /* 
         *     静态代理的一个缺点就是:我们需要为每一个接口生成一个代理类,也就是一个接口必然要对应一个代理类。这样 
         * 必然会生成很多的代理类,并且这些代理类的代码有很多重复的部分。解决这一问题,最好的办法就是通过一个代理类 
         * 完成全部的代理功能,此时就要使用动态代理。 
         */  
    }  
    

      动态代理又可以分为2种:JDK的动态代理和CGLIB的动态代理,JDK的动态代理依赖具体的接口,需要绑定接口,如果一个类没有实现接口,
    则不能使用JDK的动态代理。CGLIB的动态代理不依赖具体的接口,功能更加强大。下面我们分别进行说明,JDK的动态代理的关键是
    InvocationHandler接口,先来看JDK的动态代理:

    /** 
     * @description 代理模式 之 JDK的动态代理 -- DynamicProxyInterface接口 
     * @description 一个接口 
     */  
    public interface DynamicProxyInterface {  
        public void queryInfo();  
    } 
    

      

    /** 
     * @description 代理模式 之 JDK的动态代理 -- DynamicProxyImpl实现类  
     * @description DynamicProxyImpl,在代理模式中,叫做委托类,包含业务逻辑 
     * @description 一个接口实现类 
     */  
    public class DynamicProxyImpl implements DynamicProxyInterface {  
      
        public void queryInfo() {  
            // TODO Auto-generated method stub  
            System.out.println("代理模式 之 JDK的动态代理 -- DynamicProxyImpl实现类   查看信息...");  
        }  
    }  
    

      

    import java.lang.reflect.InvocationHandler;  
    import java.lang.reflect.Method;  
    import java.lang.reflect.Proxy;  
    /** 
     * @description 代理模式 之 JDK的动态代理 -- DynamicProxy代理类 
     * @description DynamicProxy,在代理模式中,叫做代理类,增强DynamicProxyImpl实现类  
     * @description 一个代理类,实现了InvocationHandler接口 
     * @description JDK的动态代理 与 静态代理的区别就在这个代理类,静态代理类直接实现接口,而JDK的动态代理类不 
     * 直接实现具体的接口,而是实现了JDK提供的InvocationHandler接口。 
     */  
    public class DynamicProxy implements InvocationHandler {  
        // 目标实现类,也就是某个接口的实现类,这里的target_interface_implements,可以看做是一种抽象  
        private Object target_interface_implements;  
        // 带参数构造方法,把目标实现类的对象作为参数传递进去,这里不是覆盖具体某个实现类的构造方法,而是抽象出来一个方法  
        public Object dynamicBindImplToProxyClass(Object target_interface_implements){  
            this.target_interface_implements = target_interface_implements;  
            // 取得代理对象  
            return Proxy.newProxyInstance(target_interface_implements.getClass().getClassLoader(),   
                    target_interface_implements.getClass().getInterfaces(), this);  
            // JDK的动态代理依赖具体的接口,需要绑定接口,如果一个类没有实现接口,则不能使用JDK的动态代理  
        }  
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
            // TODO Auto-generated method stub  
            Object result = null;  
            // 事务处理之前,可以执行一段代码  
            System.out.println("事务处理之前...");  
            // 执行方法  
            result = method.invoke(target_interface_implements, args);  
            // 事务处理之后,可以执行一段代码  
            System.out.println("事务处理之后...");  
            return result;  
        }  
    }
    

      

    package com.ebank.action;  
    /** 
     * @description 代理模式 之 JDK的动态代理 
     * @description 测试类DynamicProxyTest 
     * @description 动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。 
     * @description JDK的动态代理组成要素: 
     * 1,一个接口 
     * 2,一个接口实现类 
     * 3,一个代理类,实现了InvocationHandler接口 
     */  
    public class DynamicProxyTest {  
        public static void main(String[] args){  
            DynamicProxy dynamicProxy = new DynamicProxy();  
            DynamicProxyInterface dynamicProxyForImpl = (DynamicProxyInterface) dynamicProxy.dynamicBindImplToProxyClass(new DynamicProxyImpl());  
            dynamicProxyForImpl.queryInfo();  
        }  
        /* 
         *    JDK的动态代理依靠具体的接口,如果有些类并没有实现,则不能使用JDK的动态代理,这时候就需要 
         * 使用CGLIB的动态代理 
         * // JDK的动态代理的关键是InvocationHandler接口 
         */  
    }  
    

      

     接下来我们来分析一下JDK的动态代理的实现原理,JDK实现的动态代理,我们可以狭义的理解为,通过实现InvocationHandler接口,而实现的
    动态代理。JDK的动态代理的实现需要依赖接口。拿上面的JDK的动态代理的示例代码来说,DynamicProxyImpl这个类,必须要实现某个接口,才
    能借助InvocationHandler来实现动态代理,因为Proxy.newProxyInstance()这个方法中,需要传入代理类的接口作为参数。在示例中,我们的
    DynamicProxyImpl类实现了DynamicProxyInterface接口。我们实现首先来看InvocationHandler接口的源代码:

    package java.lang.reflect;  
    public interface InvocationHandler {  
        /** 
         * Processes a method invocation on a proxy instance and returns the result.  This method will be invoked on an invocation  
         * handler when a method is invoked on a proxy instance that it is associated with. 
         * Processes : 处理,加工,审核 
         * @param   proxy--the proxy instance that the method was invoked on 
         * 
         * @param   method--the Method instance corresponding to the interface method invoked on the proxy instance.  The declaring 
         * class of the Method object will be the interface that the method was declared in, which may be a  
         * superinterface of the proxy interface that the proxy class inherits the method through. 
         * 
         * @param   args--an array of objects containing the values of the arguments passed in the method invocation on the proxy  
         * instance, or null if interface method takes no arguments.Arguments of primitive types are wrapped in instances of the 
         * appropriate primitive wrapper class, such as Integer or Boolean. 
         * primitive : 简单的,这里个人理解为基本的,primitive type 意为基本数据类型 
         * @return  the value to return from the method invocation on the proxy instance.  If the declared return type of the interface 
         * method is a primitive type, then the value returned by this method must be an instance of the corresponding primitive 
         * wrapper class; otherwise, it must be a type assignable to the declared return type.  If the value returned by this method is 
         * null and the interface method's return type is primitive, then a NullPointerException will be 
         * thrown by the method invocation on the proxy instance.  If the value returned by this method is otherwise not compatible with 
         * the interface method's declared return type as described above, a ClassCastException will be thrown by the method 
         * invocation on the proxy instance. 
         */  
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;  
    }  
    

      然后,我们来看CGLIB的动态代理,CGLIB的动态代理的关键是MethodInterceptor接口,这个接口位于:net.sf.cglib.proxy.MethodInterceptor

    /** 
     * @description 代理模式 之 CGLIB的动态代理 -- CglibDynamicProxyImpl类  
     * @description CglibDynamicProxyImpl,在代理模式中,叫做委托类,包含业务逻辑 
     * @description 一个没有实现接口的类 
     */  
    public class CglibDynamicProxyImpl {  
        public void queryInfo() {  
            // TODO Auto-generated method stub  
            System.out.println("代理模式 之 CGLIB的动态代理 -- CglibDynamicProxyImpl类   查看信息...");  
        }  
    } 
    

      

    import java.lang.reflect.Method;  
    import net.sf.cglib.proxy.Enhancer;  
    import net.sf.cglib.proxy.MethodInterceptor;  
    import net.sf.cglib.proxy.MethodProxy;  
    /** 
     * @description 代理模式 之 CGLIB的动态代理 -- CglibDynamicProxy代理类 
     * @description CglibDynamicProxy,在代理模式中,叫做代理类,增强DynamicProxyImpl实现类  
     * @description 一个代理类,实现了MethodInterceptor接口 
     * @description CGLIB的动态代理 与 静态代理的区别就在这个代理类,静态代理类直接实现接口,而CGLIB的动态代理类不 
     * 直接实现具体的接口,而是实现了MethodInterceptor接口。 
     */  
    public class CglibDynamicProxy implements MethodInterceptor {  
        // 目标实现类,也就是某个接口的实现类,这里的target_interface_implements,可以看做是一种抽象  
        private Object target_class;  
        // 创建代理对象  
        public Object getInstance(Object target_class){  
            this.target_class = target_class;  
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(this.target_class.getClass());  
            // 回调方法  
            enhancer.setCallback(this);  
            // 创建代理对象  
            return enhancer.create();  
        }  
        // 回调方法  
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {  
            // 事务处理之前,可以执行一段代码  
            System.out.println("事务处理之前...");  
            // 执行方法  
            proxy.invokeSuper(arg0, arg2);  
            // 事务处理之后,可以执行一段代码  
            System.out.println("事务处理之后...");  
            return null;  
        }  
    } 
    

      

    /** 
     * @description 代理模式 之 CGLIB的动态代理 
     * @description 测试类CglibDynamicProxyTest 
     * @description 动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。 
     * @description CGLIB的动态代理组成要素: 
     * 1,一个类 
     * 2,一个代理类,实现了MethodInterceptor接口 
     */  
    public class CglibDynamicProxyTest {  
          
        public static void main(String[] args){  
            CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy();  
            CglibDynamicProxyImpl cglibDynamicProxyImpl = (CglibDynamicProxyImpl) cglibDynamicProxy.getInstance(new CglibDynamicProxyImpl());  
            cglibDynamicProxyImpl.queryInfo();  
        }  
        // CGLIB的动态代理的关键是MethodInterceptor接口  
    }  
    

       CGLIB实现的动态代理,要求委托类不能被final关键字修饰,因为在运行期间,通过Java的反射机制,会生成委托类的子类。我们都知道,一个
    类,一旦被final关键字修饰,那么这个类就不能被继承。假如我们使用final关键字修饰了委托类,编译期间不会报错,但是程序运行时,会报错:
    不能继承final类,如下:

    1. Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class class com.yangcq.CglibDynamicProxyImpl  
    2. at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)  
    3. at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)  
    4. at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)  
    5. at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)  
    6. at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)  
    7. at com.ebank.action.CglibDynamicProxy.getInstance(CglibDynamicProxy.java:24)  
    8. at com.ebank.action.CglibDynamicProxyTest.main(CglibDynamicProxyTest.java:14)  

    CGLIB的动态代理的实现原理是什么样的呢?CGLIB为我们提供了MethodInterceptor接口,我们不需要依赖某个接口,也就是说,即使代理类没有
    实现任何接口,也是可以借助CGLIB来实现动态代理的。CGLIB是借助Java反射机制,在运行期间为代理类生成一个子类,通过子类,来完成父类的动
    态代理。下面我们来看一下MethodInterceptor的源代码:

    package net.sf.cglib.proxy;  
    import java.lang.reflect.Method;  
    public abstract interface MethodInterceptor extends Callback{  
        public abstract Object intercept(Object paramObject, Method paramMethod, Object[] paramArrayOfObject,   
                MethodProxy paramMethodProxy) throws Throwable;  
    } 
    

      实现动态代理,我们需要关注一个关键的类:public class Proxy implements java.io.Serializable
    Proxy的源代码:

    package java.lang.reflect;  
    import java.lang.ref.Reference;  
    import java.lang.ref.WeakReference;  
    import java.util.Arrays;  
    import java.util.Collections;  
    import java.util.HashMap;  
    import java.util.HashSet;  
    import java.util.Map;  
    import java.util.Set;  
    import java.util.WeakHashMap;  
    import sun.misc.ProxyGenerator;  
    public class Proxy implements java.io.Serializable {  
      
        private static final long serialVersionUID = -2222568056686623797L;  
        private final static String proxyClassNamePrefix = "$Proxy";  
        private final static Class[] constructorParams = { InvocationHandler.class };  
        private static Map loaderToCache = new WeakHashMap();  
        private static Object pendingGenerationMarker = new Object();  
        private static long nextUniqueNumber = 0;  
        private static Object nextUniqueNumberLock = new Object();  
        private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());  
        protected InvocationHandler h;  
        // 私有构造函数,不允许程序员通过构造函数来实例化Proxy,生成Proxy的实例,需要调用newProxyInstance方法  
        private Proxy() {  
        }  
        // 受保护的构造函数,这个函数也不允许程序员直接调用  
        protected Proxy(InvocationHandler h) {  
            this.h = h;  
        }  
      
        public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{  
            // 这行代码,可以说明,在Class类文件的数据结构中,接口interfaces占用2个字节,最大值65535  
            if (interfaces.length > 65535) {  
                throw new IllegalArgumentException("interface limit exceeded");  
            }  
            Class proxyClass = null;  
            String[] interfaceNames = new String[interfaces.length];  
            // Set是无序,不可重复的集合  
            Set interfaceSet = new HashSet();  
            for (int i = 0; i < interfaces.length; i++) {  
                String interfaceName = interfaces[i].getName();  
                Class interfaceClass = null;  
                try {  
                    // 通过接口名称和类加载器,获得接口实现类  
                    interfaceClass = Class.forName(interfaceName, false, loader);  
                }   
                catch (ClassNotFoundException e) {  
                }  
                if (interfaceClass != interfaces[i]) {  
                    throw new IllegalArgumentException(interfaces[i] + " is not visible from class loader");  
                }  
                if (!interfaceClass.isInterface()) {  
                    throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");  
                }  
                if (interfaceSet.contains(interfaceClass)) {  
                    throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());  
                }  
                interfaceSet.add(interfaceClass);  
                interfaceNames[i] = interfaceName;  
            }  
            Object key = Arrays.asList(interfaceNames);  
            Map cache;  
            synchronized (loaderToCache) {  
                cache = (Map) loaderToCache.get(loader);  
                if (cache == null) {  
                    cache = new HashMap();  
                    loaderToCache.put(loader, cache);  
                }  
            }  
            synchronized (cache) {  
                do {  
                    Object value = cache.get(key);  
                    if (value instanceof Reference) {  
                        proxyClass = (Class) ((Reference) value).get();  
                    }  
                    if (proxyClass != null) {  
                        return proxyClass;  
                    }   
                    else if (value == pendingGenerationMarker) {  
                        try {  
                            cache.wait();  
                        }   
                        catch (InterruptedException e) {  
                        }  
                        continue;  
                    }   
                    else {  
                        cache.put(key, pendingGenerationMarker);  
                        break;  
                    }  
                } while (true);  
            }  
            try {  
                String proxyPkg = null;  
                for (int i = 0; i < interfaces.length; i++) {  
                    int flags = interfaces[i].getModifiers();  
                    if (!Modifier.isPublic(flags)) {  
                        String name = interfaces[i].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 = "";  
                }  
                {  
                    long num;  
                    synchronized (nextUniqueNumberLock) {  
                        num = nextUniqueNumber++;  
                    }  
                    String proxyName = proxyPkg + proxyClassNamePrefix + num;  
                    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);  
                    try {  
                        proxyClass = defineClass0(loader, proxyName,  
                        proxyClassFile, 0, proxyClassFile.length);  
                    }   
                    catch (ClassFormatError e) {  
                        throw new IllegalArgumentException(e.toString());  
                    }  
                }  
                proxyClasses.put(proxyClass, null);  
            }   
            finally {  
                synchronized (cache) {  
                    if (proxyClass != null) {  
                        cache.put(key, new WeakReference(proxyClass));  
                    }   
                    else {  
                        cache.remove(key);  
                    }  
                    cache.notifyAll();  
                }  
            }  
            return proxyClass;  
        }  
      
        public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  
                throws IllegalArgumentException{  
            if (h == null) {  
                throw new NullPointerException();  
            }  
            // 获得代理类,需要传递2个参数,类加载器和接口  
            Class cl = getProxyClass(loader, interfaces);  
            try {  
                // 获得代理类的构造函数  
                Constructor cons = cl.getConstructor(constructorParams);  
                // 通过构造函数,生成实例对象  
                return (Object) cons.newInstance(new Object[] { h });  
            }   
            catch (NoSuchMethodException e) {  
                throw new InternalError(e.toString());  
            }   
            catch (IllegalAccessException e) {  
                throw new InternalError(e.toString());  
            }   
            catch (InstantiationException e) {  
                throw new InternalError(e.toString());  
            }   
            catch (InvocationTargetException e) {  
                throw new InternalError(e.toString());  
            }  
        }  
      
        public static boolean isProxyClass(Class<?> cl) {  
            if (cl == null) {  
                throw new NullPointerException();  
            }  
            return proxyClasses.containsKey(cl);  
        }  
      
        public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException{  
            if (!isProxyClass(proxy.getClass())) {  
                throw new IllegalArgumentException("not a proxy instance");  
            }  
            Proxy p = (Proxy) proxy;  
            return p.h;  
        }  
        private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);  
    } 
    

      

    1. package java.lang.reflect;  
    2. import java.lang.ref.Reference;  
    3. import java.lang.ref.WeakReference;  
    4. import java.util.Arrays;  
    5. import java.util.Collections;  
    6. import java.util.HashMap;  
    7. import java.util.HashSet;  
    8. import java.util.Map;  
    9. import java.util.Set;  
    10. import java.util.WeakHashMap;  
    11. import sun.misc.ProxyGenerator;  
    12. public class Proxy implements java.io.Serializable {  
    13.   
    14.     private static final long serialVersionUID = -2222568056686623797L;  
    15.     private final static String proxyClassNamePrefix = "$Proxy";  
    16.     private final static Class[] constructorParams = { InvocationHandler.class };  
    17.     private static Map loaderToCache = new WeakHashMap();  
    18.     private static Object pendingGenerationMarker = new Object();  
    19.     private static long nextUniqueNumber = 0;  
    20.     private static Object nextUniqueNumberLock = new Object();  
    21.     private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());  
    22.     protected InvocationHandler h;  
    23.     // 私有构造函数,不允许程序员通过构造函数来实例化Proxy,生成Proxy的实例,需要调用newProxyInstance方法  
    24.     private Proxy() {  
    25.     }  
    26.     // 受保护的构造函数,这个函数也不允许程序员直接调用  
    27.     protected Proxy(InvocationHandler h) {  
    28.         this.h = h;  
    29.     }  
    30.   
    31.     public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{  
    32.         // 这行代码,可以说明,在Class类文件的数据结构中,接口interfaces占用2个字节,最大值65535  
    33.         if (interfaces.length > 65535) {  
    34.             throw new IllegalArgumentException("interface limit exceeded");  
    35.         }  
    36.         Class proxyClass = null;  
    37.         String[] interfaceNames = new String[interfaces.length];  
    38.         // Set是无序,不可重复的集合  
    39.         Set interfaceSet = new HashSet();  
    40.         for (int i = 0; i < interfaces.length; i++) {  
    41.             String interfaceName = interfaces[i].getName();  
    42.             Class interfaceClass = null;  
    43.             try {  
    44.                 // 通过接口名称和类加载器,获得接口实现类  
    45.                 interfaceClass = Class.forName(interfaceName, false, loader);  
    46.             }   
    47.             catch (ClassNotFoundException e) {  
    48.             }  
    49.             if (interfaceClass != interfaces[i]) {  
    50.                 throw new IllegalArgumentException(interfaces[i] + " is not visible from class loader");  
    51.             }  
    52.             if (!interfaceClass.isInterface()) {  
    53.                 throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");  
    54.             }  
    55.             if (interfaceSet.contains(interfaceClass)) {  
    56.                 throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());  
    57.             }  
    58.             interfaceSet.add(interfaceClass);  
    59.             interfaceNames[i] = interfaceName;  
    60.         }  
    61.         Object key = Arrays.asList(interfaceNames);  
    62.         Map cache;  
    63.         synchronized (loaderToCache) {  
    64.             cache = (Map) loaderToCache.get(loader);  
    65.             if (cache == null) {  
    66.                 cache = new HashMap();  
    67.                 loaderToCache.put(loader, cache);  
    68.             }  
    69.         }  
    70.         synchronized (cache) {  
    71.             do {  
    72.                 Object value = cache.get(key);  
    73.                 if (value instanceof Reference) {  
    74.                     proxyClass = (Class) ((Reference) value).get();  
    75.                 }  
    76.                 if (proxyClass != null) {  
    77.                     return proxyClass;  
    78.                 }   
    79.                 else if (value == pendingGenerationMarker) {  
    80.                     try {  
    81.                         cache.wait();  
    82.                     }   
    83.                     catch (InterruptedException e) {  
    84.                     }  
    85.                     continue;  
    86.                 }   
    87.                 else {  
    88.                     cache.put(key, pendingGenerationMarker);  
    89.                     break;  
    90.                 }  
    91.             } while (true);  
    92.         }  
    93.         try {  
    94.             String proxyPkg = null;  
    95.             for (int i = 0; i < interfaces.length; i++) {  
    96.                 int flags = interfaces[i].getModifiers();  
    97.                 if (!Modifier.isPublic(flags)) {  
    98.                     String name = interfaces[i].getName();  
    99.                     int n = name.lastIndexOf('.');  
    100.                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));  
    101.                     if (proxyPkg == null) {  
    102.                         proxyPkg = pkg;  
    103.                     }   
    104.                     else if (!pkg.equals(proxyPkg)) {  
    105.                         throw new IllegalArgumentException("non-public interfaces from different packages");  
    106.                     }  
    107.                 }  
    108.             }  
    109.             if (proxyPkg == null) {  
    110.                 proxyPkg = "";  
    111.             }  
    112.             {  
    113.                 long num;  
    114.                 synchronized (nextUniqueNumberLock) {  
    115.                     num = nextUniqueNumber++;  
    116.                 }  
    117.                 String proxyName = proxyPkg + proxyClassNamePrefix + num;  
    118.                 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);  
    119.                 try {  
    120.                     proxyClass = defineClass0(loader, proxyName,  
    121.                     proxyClassFile, 0, proxyClassFile.length);  
    122.                 }   
    123.                 catch (ClassFormatError e) {  
    124.                     throw new IllegalArgumentException(e.toString());  
    125.                 }  
    126.             }  
    127.             proxyClasses.put(proxyClass, null);  
    128.         }   
    129.         finally {  
    130.             synchronized (cache) {  
    131.                 if (proxyClass != null) {  
    132.                     cache.put(key, new WeakReference(proxyClass));  
    133.                 }   
    134.                 else {  
    135.                     cache.remove(key);  
    136.                 }  
    137.                 cache.notifyAll();  
    138.             }  
    139.         }  
    140.         return proxyClass;  
    141.     }  
    142.   
    143.     public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  
    144.             throws IllegalArgumentException{  
    145.         if (h == null) {  
    146.             throw new NullPointerException();  
    147.         }  
    148.         // 获得代理类,需要传递2个参数,类加载器和接口  
    149.         Class cl = getProxyClass(loader, interfaces);  
    150.         try {  
    151.             // 获得代理类的构造函数  
    152.             Constructor cons = cl.getConstructor(constructorParams);  
    153.             // 通过构造函数,生成实例对象  
    154.             return (Object) cons.newInstance(new Object[] { h });  
    155.         }   
    156.         catch (NoSuchMethodException e) {  
    157.             throw new InternalError(e.toString());  
    158.         }   
    159.         catch (IllegalAccessException e) {  
    160.             throw new InternalError(e.toString());  
    161.         }   
    162.         catch (InstantiationException e) {  
    163.             throw new InternalError(e.toString());  
    164.         }   
    165.         catch (InvocationTargetException e) {  
    166.             throw new InternalError(e.toString());  
    167.         }  
    168.     }  
    169.   
    170.     public static boolean isProxyClass(Class<?> cl) {  
    171.         if (cl == null) {  
    172.             throw new NullPointerException();  
    173.         }  
    174.         return proxyClasses.containsKey(cl);  
    175.     }  
    176.   
    177.     public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException{  
    178.         if (!isProxyClass(proxy.getClass())) {  
    179.             throw new IllegalArgumentException("not a proxy instance");  
    180.         }  
    181.         Proxy p = (Proxy) proxy;  
    182.         return p.h;  
    183.     }  
    184.     private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);  
  • 相关阅读:
    目前流行的缺陷管理工具
    高性能WEB开发之Web性能测试工具推荐
    测试工具
    简单的事件示例代码
    C#常用代码片段备忘
    C# 获取变量或对象的栈与堆地址
    C#常用的命名规则汇总
    C# 成员默认访问权限(public、private、protected、internal)
    C# 学习路线
    简单的异常例子
  • 原文地址:https://www.cnblogs.com/zhangyongJava/p/8297756.html
Copyright © 2011-2022 走看看