Android动态代理的源码分析

Android动态代理的源码分析

Android的动态代理和jdk中的动态代理的原理是一样的,但是实现上不一样。

这也是为什么Android的动态代理在MainActivity的onCreate方法中可以使用。理论上,app运行时,apk里面是dex文件,没有class文件了,而如果使用jdk的Proxy来生成class,在android中是无法加载的,因为android默认只认dex文件。

当然,也可以自己生成一个dex或jar,放在apk的/data/data/pkgName/文件夹中,再用DexClassLoader加载。jdk的Proxy没有这样的功能,于是Android就有了自己的动态代理Proxy。


Proxy的newProxyInstance的代码如下:

public static Object newProxyInstance(ClassLoader loader, Class[]interfaces, InvocationHandler h)

    throws IllegalArgumentException{

    if (h==null) {

        throw

new NullPointerException();

    }

    /*

     * Look up or generate the designatedproxy class.

     */


Class cl =getProxyClass0(loader, interfaces);


try{

        finalConstructor cons = cl.getConstructor(constructorParams);

        returnnewInstance(cons, h);

    }catch (NoSuchMethodExceptione) {

        throw

new InternalError(e.toString());

    }

}


getProxyClass0方法是查找或生成代理类。然后通过newInstance创建代理类的实例。


Proxy中缓存已经动态代理过的接口的数据结构是loaderToCache,它是一个Map。key为ClassLoader,value为Map, Object>。因为它需要缓存每一个ClassLoader生成的动态代理类的对象。不同的ClassLoader加载的对象肯定是不同的。

而对于每一个ClassLoader,它生成的动态代理类的对象也构成一个Map,key就是这个动态代理类代理的接口生成的List,value就是这个动态代理类的WeakReference。

private static Map, Object>>loaderToCache =new WeakHashMap<>();


Proxy还有一个proxyClasses,它是一个Map,提供给isProxyClass方法来检测一个类是否是代理类。key是代理类class的弱引用,value永远是null,相当于一个WeakContainer。因为isProxyClass并非一个高频调用的方法,所以简单的使用了Collections.synchronizedMap作了一个封装,实现线程安全。

/** set of allgenerated proxy classes, for isProxyClass implementation */

private static Map, Void>proxyClasses=

    Collections.synchronizedMap(new WeakHashMap, Void>());


public static booleanisProxyClass(Class cl) {

    if (cl==null) {

        throw

new NullPointerException();

    }

    return proxyClasses.containsKey(cl);

}




getProxyClass0的源码如下:

private static Class getProxyClass0(ClassLoader loader, Class...interfaces) {


if (interfaces.length > 65535) {


throw

new IllegalArgumentException("interface

limit exceeded");

    }

    Class proxyClass =

null;


/*collect interface names to use as key for proxy class cache */

    //收集所有接口,用作缓存的key


String[]

interfaceNames = new String[interfaces.length];


 // for detecting duplicates,防止出现重复的接口


Set>

interfaceSet = new HashSet<>();

[if !supportLineBreakNewLine]

[endif]

    //合法性检查:

    1.确保所有的interfaces中的名称是接口,并且是可以直接Class.forName可以找到的

    2.没有重复的接口


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");

        }


/*

         * Verify that the Class objectactually represents an

         * interface.

         */


if (!interfaceClass.isInterface()) {


throw

new IllegalArgumentException(

                interfaceClass.getName()+

" is not an interface");

        }


/*

         * Verify that this interface isnot a duplicate.

         */


if (interfaceSet.contains(interfaceClass)) {


throw

new IllegalArgumentException(


"repeated interface: " +interfaceClass.getName());

        }

        interfaceSet.add(interfaceClass);

        interfaceNames[i] =interfaceName;

    }


//cache的key


List

key = Arrays.asList(interfaceNames);



Map,Object> cache;


synchronized(loaderToCache) {

        cache =

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) {


//

proxy class already generated: return it,如果缓存中有可用的代理类,就直接返回


return proxyClass;

            }

else if (value == pendingGenerationMarker) { //使用了一个占位符,表示正在创建代理类


//

proxy class being generated: wait for it,正在创建代理类的过程中


try {

                    cache.wait();

 //wait()在while循环中使用,避免假唤醒

                }

catch (InterruptedException e) {

                             //创建代理类的时间很短,我们可以忽略这个期间的InterruptedException,不做处理,因为几乎不可能发生。


/*

                     * The classgeneration that we are waiting for should

                     * take a small,bounded time, so we can safely ignore

                     * thread interruptshere.

                     */


}


continue;

            }

else {


//使用了一个占位符,表示要开始创建代理类,break跳出循环


cache.put(key,pendingGenerationMarker);


break;

            }

        }

while (true);

    }

[if !supportLineBreakNewLine]

[endif]

    //上面验证逻辑已完成,下面开始生成代理类    try {

        String proxyPkg =

null;    // package to define proxy class in

        /*

         * Record the package of anon-public proxy interface so that the

         * proxy class will be defined inthe same package.  Verify that

         * all non-public proxyinterfaces are in the same package.

         */

        // 如果interfaces中有非public的接口,那么所有的非public的接口应该有相同的包名,否则会报错。因为不能够相互访问。

        //如果全部是public的接口,那么生成的代理类的包名proxyPkg就是一个空串。如果有非public的接口,那么代理类就和

        //这个接口在同一个包中,以使得生成的proxyClass可以访问这个接口。


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) {


// if nonon-public proxy interfaces, use the default package.


proxyPkg = "";

        }

        {


//Android-changed: Generate the proxy directly instead of calling

            // through to ProxyGenerator.

            //将所有接口的method都放在methods这个List中


Listmethods = getMethods(interfaces);

            //将methods列表按照它们所在的类的继承关系进行排序,父类方法在前,子类方法在后

            Collections.sort(methods,ORDER_BY_SIGNATURE_AND_SUBTYPE);

                 //验证没有两个方法的名称和参数都相同,返回值不同。

            validateReturnTypes(methods);

               //生成所有的exception列表

            List[]>exceptions = deduplicateAndGetExceptions(methods);

            Method[] methodsArray =methods.toArray(

new Method[methods.size()]);

            Class[][]exceptionsArray = exceptions.toArray(

new Class[exceptions.size()][]);


/*

             * Choose a name for theproxy class to generate.

             */


final

long num;


synchronized(nextUniqueNumberLock) {

                num =

nextUniqueNumber++;

            }

            //代理类包名:如果所有的接口是public的,那么proxyPkg就是空字符串,如果有一个非public接口,proxyPkg就

                 //和这个接口的包名一样。

                 //代理类的类名: $ProxyN

            String proxyName = proxyPkg +proxyClassNamePrefix + num;


//使用native的方法生成了代理类,并将这个代理类加载进来了

                 proxyClass = generateProxy(proxyName,interfaces, loader, methodsArray,

                    exceptionsArray);

        }


// addto set of all generated proxy classes, for isProxyClass.

          // 为了支持isProxyClass检测,生成的类放在proxyClasses中


proxyClasses.put(proxyClass, null);

    }

finally {


//如果成功的生成了代理类,就将它的弱引用缓存在cache中,否则,将它的key从cache中删除。并且通知所有等待代理类     //生成的线程退出阻塞。


synchronized(cache) {


if (proxyClass != null) {

                cache.put(key,

new WeakReference>(proxyClass));

            }

else {

                cache.remove(key);

            }

            cache.notifyAll();

        }

    }


return proxyClass;

}

你可能感兴趣的:(Android动态代理的源码分析)