直奔主題,不說廢話.先看java使用Proxy創建代理對象的代碼.
//一個開發者接口
public interface Developer { String code(); void debug(); }
//一個具體的開發者,實現兩個接口
public class JavaDeveloper implements Developer { private String name; public JavaDeveloper(String name) { this.name = name; } @Override public String code() { System.out.println(name + "寫代碼"); return "寫好了"; } @Override public void debug() { System.out.println(name + "調試bug"); } }
public class JavaDynamicProxy { public static void main(String[] args) { /*這個根據情況自行輸入,主要功能是將生成出的代理對象Class文件存到本地. 我用的idea編輯器,最終生成的文件在 工作空間下的 com\sun\proxy 文件夾中*/ System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //具體類,需要增強的類 JavaDeveloper zack = new JavaDeveloper("Zack"); /*Proxy.newProxyInstance 方法三個參數 * 1 一個類加載器 * 2 需要增強的類都實現了哪些接口,或哪些父類.這個很重要,因為最終生成的代理類,是要重寫父類的方法的. * 3 一個調用處理器.是一個接口,需要實現接口中的方法,就一個invoke().這個方法很重要,你使用代理對象中的方法, * 每次都會經過這個方法.這也就是增強的核心.invoke()的三個參數 * 1 需要增強原始對象.這里需要指定一個原型方法. * 2 即將執行的增強方法,這個Method 當你調用代理對象的A方法,這個Method就是A方法的Class對象. * 3 方法參數.A方法的參數. 熟悉反射的朋友應該能理解,一個Method方法執行,需要一個實例對象,和方法參數列表. * */ Developer zackProxy = (Developer) Proxy.newProxyInstance(zack.getClass().getClassLoader(), zack.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* 我這里分別對兩個方法進行了不同的增強.需要注意的是 返回值 * 如果你的方法沒有返回值可以 return null*/ if (method.getName().equals("code")) { System.out.println("正在祈禱....."); method.invoke(zack, args); return "動態的寫好了"; } if (method.getName().equals("debug")) { System.out.println("已經祈禱了,怎么還有bug"); method.invoke(zack, args); } return null; } }); //使用代理對象 String s = zackProxy.code(); zackProxy.debug(); System.out.println(s); /*打印結果 正在祈禱..... Zack寫代碼 已經祈禱了,怎么還有bug Zack調試bug 動態的寫好了*/ } }
我這里不關注代理對象的生成.有興趣的可以自行查看.下邊是生成代理對象的Class源文件,經過反編譯后.
/*注意 當前反編譯文件其中還有hashCode()toString()equals(Object obj)三個Object的方法.
這三個方法都是Object中可以被覆蓋的方法.這也就是Proxy.newProxyInstance()方法第二個參數
的作用.*/
public final class $Proxy0 extends Proxy
implements Developer {
//這里我把object的方法去掉了.直奔主題
private static Method m3;//debug 自定義的方法
private static Method m4;//code 自定義的方法
static {
try {
//初始化了兩個Method,通過類名創建Class對象,在通過方法名獲取Method對象.
m3 = Class.forName("sis.proxytest.Developer").getMethod("debug", new Class[0]);
m4 = Class.forName("sis.proxytest.Developer").getMethod("code", new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
public $Proxy0(InvocationHandler invocationhandler) {
// 這里我把父類也就是 Proxy 部分代碼貼上.
// protected InvocationHandler h;//父類成員變量
// protected Proxy(InvocationHandler h) {//父類構造子
// Objects.requireNonNull(h);
// //就是把我們new出來的 InvocationHandler傳遞給了父類
// this.h = h;
// }
super(invocationhandler);
}
//這才是重點
public final void debug() {
try {
/* 當我們使用代理對象調用 debug()方法時.會使用父類Proxy的h成員變量的invoke()
這個h就是我們開篇使用Proxy.newProxyInstance創建代理對象中的第三個參數*/
super.h.invoke(this, m3, null);
return;
} catch (Error) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String code() {
try {
return (String) super.h.invoke(this, m4, null);
} catch (Error) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
以上就是Proxy生成代理對象,是如果使用invoke()方法的過程.如有不足請補充.
