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;
}