使用
動(dòng)態(tài)代理有兩個(gè)對(duì)象锻梳,目標(biāo)對(duì)象和代理對(duì)象。使用JDK動(dòng)態(tài)代理净捅,目標(biāo)對(duì)象必須實(shí)現(xiàn)一個(gè)接口疑枯。
public class JdkDynamicProxyTest {
interface IPerson {
void say() ;
}
static class Person implements IPerson {
@Override
public void say() {
System.out.println("hello world");
}
}
static class JdkProxy implements InvocationHandler {
//目標(biāo)對(duì)象
private Object target;
//得到代理對(duì)象
public Object getProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("say before");
method.invoke(target, args);
System.out.println("say after");
return null;
}
}
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
JdkProxy jdkProxy = new JdkProxy();
IPerson person = (IPerson) jdkProxy.getProxy(new Person());
person.say();
}
}
原理
要查看JDK動(dòng)態(tài)代理原理,只需要在運(yùn)行的時(shí)候蛔六,增加下面一句話:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
會(huì)在項(xiàng)目路徑下生成一個(gè)$Proxy0.class文件荆永,反編譯這個(gè)文件,就能夠明白JDK動(dòng)態(tài)代理原理国章。
final class $Proxy0 extends Proxy implements IPerson {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.ming.aop.IPerson").getMethod("say");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
代理的大概結(jié)構(gòu)包括4部分:
靜態(tài)字段:被代理的接口所有方法都有一個(gè)對(duì)應(yīng)的靜態(tài)變量具钥;
靜態(tài)塊:主要是通過反射初始化靜態(tài)變量;
具體每個(gè)代理方法:邏輯都差不多就是 h.invoke液兽,h是Proxy的屬性骂删。主要是調(diào)用我們定義好的invocatinoHandler邏輯,觸發(fā)目標(biāo)對(duì)象target上對(duì)應(yīng)的方法;
public class Proxy implements java.io.Serializable {
protected InvocationHandler h;
}
構(gòu)造函數(shù):從這里傳入我們InvocationHandler邏輯;構(gòu)造函數(shù)在newProxyInstance方法中通過反射調(diào)用抵碟。
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}