一个类: Proxy 提供了一些静态方法用于创建动态代理类的Class对象或者是动态代理对象, 也是所有动态代理类的父类.
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
创建动态代理对象
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces) 创建动态代理类的Class对象.
一个接口: InvocationHandler 简单理解为实现整个代理的过程
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
在此方法中实现代理的功能并且将方法的调用转回到目标对象上.
-
相关问题解析:
a. 动态代理对象可以强制转换成目标类实现过的接口类型。 不能转换成目标类型[基于接口实现动态代理]
b. 代理对象调用代理方法,最终会执行到InvocationHandler中的invoke方法.
[1]. 调用Proxy.newProxyInstance()方法时,我们将自己创建好的InvocationHandler对象 myH 传入.
[2]. 在newProxyInstance方法中, 先获取到代理类的Class对象cl. 参考Proxy类中的 719 行.Class<?> cl = getProxyClass0(loader, intfs);
[3].在newProxyInstance方法中, 通过cl获取代理类中带有InvocationHandler参数的构造器,参考Proxy类中的729行.final Constructor<?> cons = cl.getConstructor(constructorParams);
[4].在newProxyInstance方法中, 执行获取到的构造器,将我们传入的myH传入到该构造器中. 参考Proxy类中的739行.return cons.newInstance(new Object[]{h});
[5].在代理类中的构造器中,接收到传入的myH, 并将myH通过super(h)传入到父类Proxy的构造器中。
[6].在父类Proxy的构造器中, 接收到myH, 并将myH赋值给成员变量h .
[7].当代理对象调用代理方法时,在每个代理方法中都有一行 super.h.invoke 代码, 会调用到myH中的invoke方法.
如图:
代理对象的代理类:
public final class $Proxy0 extends Proxy implements ArithmeticCalculator {
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 $Proxy0(InvocationHandler arg0) throws {
super(arg0);
}
public final boolean equals(Object arg0) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{arg0})).booleanValue();
} catch (RuntimeException | Error arg2) {
throw arg2;
} catch (Throwable arg3) {
throw new UndeclaredThrowableException(arg3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error arg1) {
throw arg1;
} catch (Throwable arg2) {
throw new UndeclaredThrowableException(arg2);
}
}
public final int mul(int arg0, int arg1) throws {
try {
return ((Integer)super.h.invoke(this, m5, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
} catch (RuntimeException | Error arg3) {
throw arg3;
} catch (Throwable arg4) {
throw new UndeclaredThrowableException(arg4);
}
}
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);
}
}
public final int sub(int arg0, int arg1) throws {
try {
return ((Integer)super.h.invoke(this, m4, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
} catch (RuntimeException | Error arg3) {
throw arg3;
} catch (Throwable arg4) {
throw new UndeclaredThrowableException(arg4);
}
}
public final int div(int arg0, int arg1) throws {
try {
return ((Integer)super.h.invoke(this, m6, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
} catch (RuntimeException | Error arg3) {
throw arg3;
} catch (Throwable arg4) {
throw new UndeclaredThrowableException(arg4);
}
}
public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error arg1) {
throw arg1;
} catch (Throwable arg2) {
throw new UndeclaredThrowableException(arg2);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m5 = Class.forName("com.atguigu.spring.aop.proxy.ArithmeticCalculator").getMethod("mul",
new Class[]{Integer.TYPE, Integer.TYPE});
m3 = Class.forName("com.atguigu.spring.aop.proxy.ArithmeticCalculator").getMethod("add",
new Class[]{Integer.TYPE, Integer.TYPE});
m4 = Class.forName("com.atguigu.spring.aop.proxy.ArithmeticCalculator").getMethod("sub",
new Class[]{Integer.TYPE, Integer.TYPE});
m6 = Class.forName("com.atguigu.spring.aop.proxy.ArithmeticCalculator").getMethod("div",
new Class[]{Integer.TYPE, Integer.TYPE});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException arg1) {
throw new NoSuchMethodError(arg1.getMessage());
} catch (ClassNotFoundException arg2) {
throw new NoClassDefFoundError(arg2.getMessage());
}
}
}