?參考?http://www.iteye.com/topic/683613
參考?http://hi.baidu.com/malecu/item/9e0edc115cb597a1feded5a0
參考 http://www.educity.cn/wenda/360356.html
參考?http://langyu.iteye.com/blog/410071
?
/** * 相親接口 * * @author zhengt * @time Jun 3, 2095 3:13:03 PM */ public interface XiangQinInterface { /** * 相親方法 */ public void xiangQin(); } /** * 張三相親實現類 * * @author zhengt * @time Jun 3, 2095 3:14:48 PM */ public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface { public void xiangQin() { System.out.println("張三去相親,娶個漂亮老婆。"); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 相親可是一輩子的大事,相親前要準備一下,打扮得帥氣些。 * * @author zhengt * @time Jun 3, 2095 3:15:48 PM */ public class ReadyInvocationHandler implements InvocationHandler { //相親接口的實現類,也就是張三相親類 private Object zhangSan = null; public ReadyInvocationHandler(Object realSubject) { this.zhangSan = realSubject; } public Object invoke(Object proxy, Method m, Object[] args) { Object result = null; try { /** * 動態代理類$Proxy0調用xiangQin方法時會調用它自己的xiangQin方法, * 而它自己的xiangQin方法里面調用的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法, * 也就是ReadyInvocationHandler類的invoke方法。 * 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實際上就是動態代理類$Proxy0, * 如果你將其強轉成XiangQinInterface然后調用它的xiangQin方法,然后它就會調用super.h.invoke(this, , ),這樣就會死循環。 */ /** * 網上關于這里最多問題就是Object proxy放在這里用來做什么呢?這個我也不知道, * 不過至少我們知道它到底是個什么東西,具體做什么用嘛就不得而知了 */ System.out.println(proxy.getClass().getSimpleName()); System.out.println("張三相親前,代理人給他打扮了打扮。"); result = m.invoke(zhangSan, args); } catch (Exception ex) { System.exit(1); } return result; } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 張三來到了婚介所(相親現場),開始相親。 * * @author zhengt * @time Jun 3, 2095 3:17:16 PM */ public class HunJieSuo { public static void main(String args[]) { //先將張三相親這個相親的實現類實例化,也就是得到XiangQinInterface接口的一個實例對象 XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl(); /** * 得到ZhangSanXiangQinInterfaceImpl這個類的一個代理類,同時為代理類綁定了一個處理類ReadyInvocationHandler。 * 聽著很繞口,其實就是每次調用ZhangSanXiangQinInterfaceImpl這個子類的xiangQin方法時, * 不是zhangSan這個ZhangSanXiangQinInterfaceImpl類的實例去調用, * 而是這個ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去調用它自己的invoke方法, * 這個invoke方法里呢可以調用zhangSan這個實例的xiangQin方法 */ /** * 在java種怎樣實現動態代理呢 * 第一步,我們要有一個接口,還要有一個接口的實現類,而這個實現類呢就是我們要代理的對象, * 所謂代理呢也就是在調用實現類的方法時,可以在方法執行前后做額外的工作,這個就是代理。 * 第二步,我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler接口, * 為什么要繼承它呢?因為代理類的實例在調用實現類的方法的時候,不會調真正的實現類的這個方法, * 而是轉而調用這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以調用真正的實現類的這個方法。 * 第三步,在要用代理類的實例去調用實現類的方法的時候,寫出下面兩段代碼。 */ // 獲得代理類($Proxy0 extends Proxy implements XiangQinInterface)的實例. XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance( zhangSan.getClass().getClassLoader(), zhangSan.getClass().getInterfaces(), new ReadyInvocationHandler(zhangSan)); proxy.xiangQin(); /** * 這里要解釋下中部那段長長的代碼的意思,以及具體做了哪些工作? * 第一,根據zhangSan.getClass().getClassLoader()這個要代理類的類加載器和 * zhangSan.getClass().getInterfaces()要代理類所實現的所有的接口 * 作為參數調用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces) * 的方法返回代理類的java.lang.Class對象,也就是得到了java動態生成的代理類$Proxy0的Class對象。 * 同時,java還讓這個動態生成的$Proxy0類實現了要代理類的實現的所有接口,并繼承了Proxy接口。 * 第二,實例化這個動態生成的$Proxy0類的一個實例,實例化代理類的構造函數為Proxy(InvocationHandler h), * 也就是說要實例化這個動態生成的$Proxy0類,必須給它一個InvocationHandler參數,也就是我們自己實現的用來在代理類 * 方法執行前后做額外工作的類ReadyInvocationHandler。 * 這段代碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan)) * 得到的其實是一個類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。 * 第三,將這個$Proxy0類強制轉型成XiangQinInterface類型,調用xiangQin方法。 */ } }
?
備注:著重看“ // 獲得代理類($Proxy0 extends Proxy implements XiangQinInterface)的實例. ”這個注解 。?
?一.相關類及其方法:
java.lang.reflect.Proxy,
Proxy 提供用于創建動態代理類和實例的靜態方法 .
newProxyInstance()
返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序
(詳見api文檔)
?
java.lang.reflect.InvocationHandler,
InvocationHandler 是代理實例的調用處理程序 實現的接口 。?
invoke()
在代理實例上處理方法調用并返回結果。在與方法關聯的代理實例上調用方法時,將在調用處理程序上調用此方法。
?
創建某一接口 Foo 的代理:?
?
InvocationHandler handler = new MyInvocationHandler(...); Class proxyClass = Proxy.getProxyClass( Foo.class.getClassLoader(), new Class[] { Foo.class }); Foo f = (Foo) proxyClass. getConstructor(new Class[] { InvocationHandler.class }). newInstance(new Object[] { handler });
?
?
或使用以下更簡單的方法:?
?
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class }, handler);
?
?
四.機制分析:
Proxy.(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下幾件事.
(1)根據參數loader和interfaces調用方法 getProxyClass(loader, interfaces)創建代理類$Proxy.
$Proxy0類實現了interfaces的接口,并繼承了Proxy類.
?
(2)實例化$Proxy0并在構造方法中把BusinessHandler傳過去,接著$Proxy0調用父類Proxy的構造器,為h賦值,如下:
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; public final class $Proxy0 extends Proxy implements XiangQinInterface { private static Method m1; private static Method m0; private static Method m3; private static Method m2; static { try { 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()); } } public $Proxy0(InvocationHandler invocationhandler) { super(invocationhandler); } @Override public final boolean equals(Object obj) { try { 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實例強制轉換成XiangQinInterface?.
當執行proxy.xiangQin()方法時,就調用了$Proxy0類中的xiangQin()方法.
在modify方法中,調用父類Proxy中的h的invoke()方法.
即InvocationHandler.invoke();?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
