Proxy动态代理的内部机制
作者:互联网
机制分析
其实JDK的动态代理,实际上就是“反射”与“执行时动态生成字节码”二者的结合体。
$Proxy0=Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)做了以下2件事。
-
根据参数 loader 和 interfaces 调用方法 Proxy 的getProxyClass(loader, interfaces)创建代理类 $Proxy0 。
$Proxy0 类实现了interfaces的接口,并继承了Proxy类。 -
实例化 $Proxy0 并在构造方法中把InvocationHandler传过去,接着 $Proxy0 调用父类 Proxy 的构造器,为h赋值
// Proxy类中有一个protected构造方法,接收一个InvocationHandler
class Proxy{
InvocationHandler h=null;
protected Proxy(InvocationHandler h) {
this.h = h;
}
...
}
// $Proxy0的部分代码如下所示
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
// IManager是代理实现的的接口,下面主要介绍了如何代理
public final class $Proxy0 extends Proxy implements IManager {
// 调用父类Proxy的构造方法传递InvocationHandler
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
....
static {
try {
// 反射得到Object的方法对象(Method对象)
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
.......
// 当调用代理类$proxy0的方法时,会回调$Proxy0=Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, // InvocationHandler h)中定义的InvocationHandler的Invoke()方法
// 三个参数:this---代理类本身$Proxy0
// m1---相对应的Method对象
// new Object[]{}---方法的参数,没有参数传null
@Override
public final boolean equals(Object obj) {
try {
// 这句代码回调了你写的invoke()方法
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
.booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void modify() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
// 下面演示&Proxy0的使用
// 把得到的$Proxy0实例强制转换成IManager类型的managerProxy.
IManager managerProxy = (Manager) Proxy.newProxyInstance(managerImpl
.getClass().getClassLoader(), managerImpl.getClass()
.getInterfaces(), invocationHandler);
$Proxy0也实现了IManager接口中的所有方法,所以当调用managerProxy.modify(),就是执行下面这些代码
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
这样动态代理机制就实现了。
所以 JAVA 的动态代理的关键就在 Proxy.newProxyInstance(…) 方法执行时生成了 $Proxy0 的内存字节码以及 JDK 的反射机制。
标签:Proxy0,代理,InvocationHandler,Proxy,throwable,new,动态,Class 来源: https://blog.csdn.net/qq_16570607/article/details/118359949