更新時間:2017-11-14 來源:黑馬程序員 瀏覽量:
機制分析:其實JDK的動態代理,實際上就是“反射”與“執行時動態生成字節碼”二者的結合體
$Proxy0=Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)做了以下2件事。
(1)根據參數loader和interfaces調用方法 Proxy的getProxyClass(loader, interfaces)創建代理類$Proxy0。
$Proxy0類實現了interfaces的接口,并繼承了Proxy類。
(2)實例化$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的反射機制!?
友情提示:獲得更多學科學習視頻+資料+源碼,請加QQ:3276250747。