原文链接: JDK动态代理实现机制   转载请注明出处!

===========================================

本文只对JDK动态代理的底层实现进行分析,如需了解代理模式和动态代理的使用请移步:设计模式—代理模式     动态代理的两种实现方式(JDK/Cglib)

在读代码之前先清楚两个概念:

  1、Class类存储的是类的所有信息,包括类的所有方法、属性、实现接口等。每个类对应一个Class对象(单例),Class对象是由classLoader加载出来的,使用双亲委派模型来保证class只会被加载一次。

  2、classLoader在加载类的时候不管class文件是从哪里来的,无论是从.class文件、网络、数据库类加载器都不关心。他只关心给他的class二进制流是不是能够通过校验。

说明:以下测试代码和 动态代理的两种实现方式(JDK/Cglib)相同

使用JDK动态代理需要实现InvocationHandler接口,同时实现invoke()方法。

iOS培训,Swift培训,苹果开发培训,移动开发培训

package com.zpj.proxy.jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/**
 * Created by Perkins on 2017/4/2. */public class JDKProxy implements InvocationHandler {    private Object person;    public Object getInstance(Object person) {        this.person = person;        return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
    }

    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("doSomething---------start");
        method.invoke(person, args);
        System.out.println("doSomething---------end");        return null;
    }
}

iOS培训,Swift培训,苹果开发培训,移动开发培训

测试代码如下:

iOS培训,Swift培训,苹果开发培训,移动开发培训

package com.zpj.proxy.jdk;/**
 * Created by Perkins on 2017/4/2. */public class Run {    public static void main(String[] args) {
        Person person = (Person) new JDKProxy().getInstance(new MrLi());
        person.doWork();
    }
}

iOS培训,Swift培训,苹果开发培训,移动开发培训

 

运行的时候在person处打断点可看到person的类名为$Proxy0而不是Person或者MrLi,则说明该返回对象是Person的实现类

iOS培训,Swift培训,苹果开发培训,移动开发培训

我们添加如下代码把person的class中的方法打印出来

iOS培训,Swift培训,苹果开发培训,移动开发培训

package com.zpj.proxy.jdk;/**
 * Created by Perkins on 2017/4/2. */import java.lang.reflect.Method;public class Run {    private Method method;    public static void main(String[] args) {
       Person person = (Person) new JDKProxy().getInstance(new MrLi());
       Method [] methods = person.getClass().getMethods();       for(int i =0; i<methods.length;i++){
           System.out.println(methods[i].getName());
       }
        person.doWork();
    }
}

iOS培训,Swift培训,苹果开发培训,移动开发培训

 

结果如下,很明显红框中的方法不属于Person也不属于Object中的方法。这更进一步说明返回的person并不是Person的实例。

iOS培训,Swift培训,苹果开发培训,移动开发培训

下面就进入底层代码对JDK动态代理进行解析。

这里直接对Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);进行分析。

 

iOS培训,Swift培训,苹果开发培训,移动开发培训

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException{        if (h == null) {        //验证InvocationHandler不允许为null
        throw new NullPointerException();
        }    /*
     * Look up or generate the designated proxy class.     */
    //调用getProxyClass()获取Class实例,该实例便是返回的代理Person的实例,此方法为重点!!!
        Class cl = getProxyClass(loader, interfaces);    /*
     * Invoke its constructor with the designated invocation handler.     */
        try {        //利用反射机制从Class中取出构造器创建对象
        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());
        }
        }

iOS培训,Swift培训,苹果开发培训,移动开发培训

 

 在上面方法中调用public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)throws IllegalArgumentException获取了Class实例,下面进入该方法进行分析。

iOS培训,Swift培训,苹果开发培训,移动开发培训

public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException {        if (interfaces.length > 65535) {            //验证接口数量不允许超过65535
            throw new IllegalArgumentException("interface limit exceeded");
        }        //************开始对interface进行循环验证,验证通过则加入interfaceNames中***************************
        Class proxyClass = null;    /* collect interface names to use as key for proxy class cache */
        String[] interfaceNames = new String[interfaces.length];
        Set interfaceSet = new HashSet();    // for detecting duplicates
        for (int i = 0; i < interfaces.length; i++) {//循环对所有接口进行操作
        /*
         * Verify that the class loader resolves the name of this
         * interface to the same Class object.         */
            String interfaceName = interfaces[i].getName();
            Class interfaceClass = null;            try {                //根据名称获取接口的Class
                interfaceClass = Class.forName(interfaceName, false, loader);
            } catch (ClassNotFoundException e) {
            }            if (interfaceClass != interfaces[i]) {                throw new IllegalArgumentException(interfaces[i] + " 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.contains(interfaceClass)) {                throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName());
            }
            interfaceSet.add(interfaceClass);
            interfaceNames[i] = interfaceName;
        }//************结束对interface进行循环验证,存储于interfaceNames中***************************
    /*
     * Using string representations of the proxy interfaces as
     * keys in the proxy class cache (instead of their Class
     * objects) is sufficient because we require the proxy
     * interfaces to be resolvable by name through the supplied
     * class loader, and it has the advantage that using a string
     * representation of a class makes for an implicit weak
     * reference to the class.     */
        Object key = Arrays.asList(interfaceNames);    /*
     * Find or create the proxy class cache for the class loader.     */
        Map cache;        synchronized (loaderToCache) {
            cache = (Map) loaderToCache.get(loader);            if (cache == null) {
                cache = new HashMap();
                loaderToCache.put(loader, cache);
            }        /*
         * This mapping will remain valid for the duration of this
         * method, without further synchronization, because the mapping
         * will only be removed if the class loader becomes unreachable.         */
        }    /*
     * Look up the list of interfaces in the proxy class cache using
     * the key.  This lookup will result in one of three possible
     * kinds of values:
     *     null, if there is currently no proxy class for the list of
     *         interfaces in the class loader,
     *     the pendingGenerationMarker object, if a proxy class for the
     *         list of interfaces is currently being generated,
     *     or a weak reference to a Class object, if a proxy class for
     *         the list of interfaces has already been generated.     */
        synchronized (cache) {        /*
         * Note that we need not worry about reaping the cache for
         * entries with cleared weak references because if a proxy class
         * has been garbage collected, its class loader will have been
         * garbage collected as well, so the entire cache will be reaped
         * from the loaderToCache map.         */
            do {
                Object value = cache.get(key);                if (value instanceof Reference) {
                    proxyClass = (Class) ((Reference) value).get();
                }                if (proxyClass != null) {                    // proxy class already generated: return it
                    return proxyClass;
                } else if (value == pendingGenerationMarker) {                    // proxy class being generated: wait for it
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {            /*
             * The class generation that we are waiting for should
             * take a small, bounded time, so we can safely ignore
             * thread interrupts here.             */
                    }                    continue;
                } else {            /*
             * No proxy class for this list of interfaces has been
             * generated or is being generated, so we will go and
             * generate it now.  Mark it as pending generation.             */
                    cache.put(key, pendingGenerationMarker);                    break;
                }
            } while (true);
        }        try {
            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.         */
        //寻找到package的包路径,为构建代理类做准备。同时要保证所有的非public代理接口在相同的包中
            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) {
                        proxyPk

http://www.cnblogs.com/PerkinsZhu/p/6658066.html