一文带你弄懂 Java 动态代理( 二 )


文章插图
Proxy源码
来看下Proxy 源码,当我们 newProxyInstance(…) 时,首先系统会进行判空处理,之后获取我们实际的 Proxy 代理类 Class 对象,再通过一个参数的构造方法生成我们的代理对象 p(p : 返回值),这里能看出来 p 是持有我们的对象 h 的 。注意 cons.setAccessible(true) 表示,即使是 cl 是私有构造,也可以获得对象 。源码见下:
 public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNon(h);
final Class<?> intfs = interfaces.clone;
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
...
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers)) {
cons.setAccessible(true);
// END Android-removed: Excluded AccessController.doPrivileged call.
}
return cons.newInstance(new Object[]{h});
...
}
其中 getProxyClass0(…) 是用来检查并获取实际代理对象的 。首先会有一个65535的接口限制检测,随后从代理缓存 ProxyClassCache 中获取代理类,如果给定的接口不存在,则通过 ProxyClassFactory 新建 。见下:
 private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
存放代理 Proxy.class 的缓存 proxyClassCache,是一个静态常量,所以在我们类加载时,其就已经被初始化完毕了 。见下:
 private static final WeakCache<ClassLoader, Class<?>, Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory, new ProxyClassFactory);
Proxy 提供的getInvocationHandler(Object proxy)方法和 invoke(…) 方法很重要 。分别为获取当前代理关联的调用处理器对象 InvocationHandler,并将当前Proxy方法调用调度给 InvocationHandler 。
是不是与上面的代理思维很像,至于这两个方法何时被调用的,推测是写在了本地方法内,当我们调用 proxy.request 方法时(系统创建Proxy时,会自动 implements 用户传递的接口,可以为多个),系统就会调用 Proxy invoke 方法,随后 proxy 将方法调用传递给 InvocationHandler 。
 public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
/*
* Verify that the object is actually a proxy instance.
*/
if (!isProxyClass(proxy.getClass)) {
throw new IllegalArgumentException("not a proxy instance");
}
final Proxy p = (Proxy) proxy;
final InvocationHandler ih = p.h;
return ih;
【一文带你弄懂 Java 动态代理】}
// Android-added: Helper method invoke(Proxy, Method, Object[]) for ART native code.
private static Object invoke(Proxy proxy, Method method, Object[] args) throws Throwable {
InvocationHandler h = proxy.h;
return h.invoke(proxy, method, args);
}

一文带你弄懂 Java 动态代理

文章插图
ProxyClassFactory
重点是ProxyClassFactory 类,这里的逻辑不少,所以我将ProxyClassFactory 单独抽出来了 。能看到,首先其会检测当前 interface 是否已被当前类加载器所加载 。
 Class<?> interfaceClass = ;
try {
interfaceClass = Class.forName(intf.getName, false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
之后会进行判断是否为接口 。这也是我们说的第二个参数为何不能传基类或抽象类的原因 。
 if (!interfaceClass.isInterface) {
throw new IllegalArgumentException(
interfaceClass.getName + " is not an interface");
}
之后判断当前 interface 是否已经存在于缓存cache内了 。
 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != ) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName);
}
检测非 public 修饰符的 interface 是否在是同一个包名,如果不是则抛出异常:


推荐阅读