protected Proxy(InvocationHandler h) {this.h = h;}
接着,可以快速浏览一下 newProxyInstance 方法,因为其相当简单:
清单 7. Proxy 静态方法 newProxyInstance
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
// 检查 h 不为空,否则抛异常
if (h == null) {
throw new NullPointerException();
}
// 获得与制定类装载器和一组接口相关的代理类类型对象
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 (IllegalAcces***ception e) { throw new InternalError(e.toString());
} catch (InstantiationException e) { throw new InternalError(e.toString());
} catch (InvocationTargetException e) { throw new InternalError(e.toString());
}
}
由此可见,动态代理真正的关键是在 getProxyClass 方法,该方法负责为一组接口动态地生成代理类类型对象。在该方法内
部,您将能看到 Proxy 内的各路英雄(静态变量)悉数登场。有点迫不及待了么?那就让我们一起走进 Proxy 最最神秘的殿堂去
欣赏一番吧。该方法总共可以分为四个步骤:
对这组接口进行一定程度的安全检查,包括检查接口类对象是否对类装载器可见并且与类装载器所能识别的接口类对象是完全
相同的,还会检查确保是 interface 类型而不是 class 类型。这个步骤通过一个循环来完成,检查通过后将会得到一个包含所
有接口名称的字符串数组,记为 String[] interfaceNames。总体上这部分实现比较直观,所以略去大部分代码,仅保留留如何
判断某类或接口是否对特定类装载器可见的相关代码。
清单 8. 通过 Class.forName 方法判接口的可见性
try {
// 指定接口名字、类装载器对象,同时制定 initializeBoolean 为 false 表示无须初始化类
// 如果方法返回正常这表示可见,否则会抛出 ClassNotFoundException 异常表示不可见
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
从 loaderToCache 映射表中获取以类装载器对象为关键字所对应的缓存表,如果不存在就创建一个新的缓存表并更新到
loaderToCache。缓存表是一个 HashMap 实例,正常情况下它将存放键值对(接口名字列表,动态生成的代理类的类对象引
用)。当代理类正在被创建时它会临时保存(接口名字列表,pendingGenerationMarker)。标记 pendingGenerationMarke 的作
用是通知后续的同类请求(接口数组相同且组内接口排列顺序也相同)代理类正在被创建,请保持等待直至创建完成。