动态代理相关的问题分析:
- 动态代理对象可以强制转换成目标对象所实现过的接口类型. 因为代理类也实现了目标类实现过的接口.
- InvocationHandler中invoke方法如何执行 ?
结论: 代理对象调用代理方法时,最终会执行到InvocationHandler中的invoke方法.
自己写的测试类
public class ArithmeticCalculatorProxy {
private Object impl;
// 创造这个对象时候给被代理类赋值
public ArithmeticCalculatorProxy(Object impl) {
this.impl = impl;
}
// 创造代理类对象
public Object getProxy() {
ClassLoader loader = impl.getClass().getClassLoader();
Class[] interfaces = impl.getClass().getInterfaces();
Object proxyInstance = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
MyLogging.beforeMethod(methodName, args);
Object invoke = method.invoke(impl, args);
MyLogging.afterMethod(methodName, invoke);
return invoke;
}
});
return proxyInstance;
}
}
源码解析:
InvocationHandler的invoke()的执行顺序:
创建代理对象时当作方法参数传进去 -->
构造器对象调用带有InvocationHandler参数的构造器用于创建代理类对象 -->
创建代理类对象把InvocationHandler传给父类Proxy给h属性赋值–>
代理类执行方法,其实执行的时super.h.invoke()方法.
不变的宗旨:
① 实例方法一定是由对象调用的
② 实例方法一定是由当前类的对象调用的。
过程:
进入Proxy代理类中执行newProxyInstance方法
1). 通过 Proxy.newProxyInstance 创建代理对象时, 传入了一个通过匿名内部类创建好的InvocationHandler类型的对象.==>myH
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
2). 在newProxyInstance方法中, 719行获取到了代理类的Class对象, 729行获取到了代理类中带 InvocationHandler参数的构造器 ,
719: Class<?> cl = getProxyClass0(loader, intfs);
729:final Constructor<?> cons = cl.getConstructor(constructorParams);
223: private static final Class<?>[] constructorParams =
{ InvocationHandler.class };//这是constructorParams的值
739行执行代理类中的带InvocationHandler参数的构造器, 将我们传入的myH传到了该构造器中.
739:return cons.newInstance(new Object[]{h});//通过反射创建代理对象并返回
下面的是自定义的代理对象的测试类
public final class $Proxy00 extends Proxy implements ArithmeticCalculator {//继承Proxy,实现被代理类实现的接口
private static Method m1;
private static Method m2;
private static Method m5;
private static Method m3;
private static Method m4;
private static Method m6;
private static Method m0;
public $Proxy00(InvocationHandler arg0) throws {
super(arg0);//调用这个构造器把InvocationHandler的实现类对象传给Proxy
}
public final int add(int arg0, int arg1) throws {
try {
//代理类中代理的方法中都有这么一行代码,参数时代理类对象,方法对象,参数
return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
} catch (RuntimeException | Error arg3) {
throw arg3;
} catch (Throwable arg4) {
throw new UndeclaredThrowableException(arg4);
}
}
}
3). 在代理类($ProxyN)中的构造器中,将我们传入的myH通过 super(h)又传入到了父类(Proxy)的构造器中。
public $Proxy00(InvocationHandler arg0) throws {
super(arg0);//调用这个构造器把InvocationHandler的实现类对象传给Proxy
}
4). 在父类(Proxy)的构造器中,将传入的myH 又赋值给了成员变量h . 看266行.
266:protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
5). 在代理类中的每个代理方法中, 都一行代码 super.h.invoke(代理对象,方法对象,方法参数);
//执行的传给Proxy的Invocation的实现类的invoke()方法;
return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
因此, 代理对象调用代理方法时, 会通过代理方法中的super.h.invoke 执行到我们自己创建的myH中的invoke方法