首先要加两点总容易疑惑的解答:
第一,newProxyInstance生成的并不是代理接口类 而是代理接口的实现类!!!
第二,动态代理本质是Proxy生成$Proxy0并代理了InvocationHandler!!!!
1.通过newProxyInstance方法中通过代理类lodar和接口实现instance生成$Proxy0类
(这个类实现了代理接口以及拥有代理所有接口的方法,并且可以传入多实现的实现类,但无法拥有继承类的实现接口方法,即使重写了父类接口的实现)
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
{
...
...
Class<?> cl = getProxyClass0(loader, intfs);//此处生成并返回一个$Proxy0类
...
...
}
2.将代理对象的实现传入$Proxy0构造方法,接着$Proxy0调用父类Proxy的构造器,为父类属性赋值(属性为InvocationHandler类型)
protected InvocationHandler h; //InvocationHandler类型的属性
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
...
...
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
...
...
}
3.newProxyInstance返回一个$Proxy0类型的参数,再强制转换成代理接口类型
4.调用方法时直接调用$Proxy0中的方法,也就是调用父类Proxy中的h.invoke
public final class $Proxy0 extends Proxy implements TestInterface2 {
...
...
public final void say() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
...
...
}
最后思考一个问题:
当代理接口有多实现时他会调用哪个实现的接口呢?
看完之后就很好理解了,调用$Proxy0.invoke时只会调用到父类Proxy的属性InvocationHandler,而这个InvocationHandler就是你的InvocationHandler实现类,而这个实现类的target就是在你newProxyInstance时传入的那个接口实现类。
最最后再思考一下:
如果代理了多接口呢?如果有同时继承了其他接口的实现类呢?
感兴趣的可以试试,答案就是可以代理多接口,newProxyInstance的参数是一个Class<?>[] interfaces,但是代理到继承类的其他接口
ps:newProxyInstance只接受接口参数类型
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
}