1. 程式人生 > >代理模式理解

代理模式理解


1./** 
2. * 相親介面 
3. *  
4. * @author zhengt 
5. * @time Jun 3, 2095 3:13:03 PM 
6. */  
7.public interface XiangQinInterface {  
8.    /** 
9.     * 相親方法 
10.     */  
11.    public void xiangQin();  
12.}  
13./** 
14. * 張三相親實現類 
15. *  
16. * @author zhengt 
17. * @time Jun 3, 2095 3:14:48 PM 
18. */  
19.public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface {  
20.    public void xiangQin() {  
21.        System.out.println("張三去相親,娶個漂亮老婆。");  
22.    }  
23.}  
24.import java.lang.reflect.InvocationHandler;  
25.import java.lang.reflect.Method;  
26.  
27./** 
28. * 相親可是一輩子的大事,相親前要準備一下,打扮得帥氣些。 
29. *  
30. * @author zhengt 
31. * @time Jun 3, 2095 3:15:48 PM 
32. */  
33.public class ReadyInvocationHandler implements InvocationHandler {  
34.    //相親介面的實現類,也就是張三相親類  
35.    private Object zhangSan = null;  
36.  
37.    public ReadyInvocationHandler(Object realSubject) {  
38.        this.zhangSan = realSubject;  
39.    }  
40.  
41.    public Object invoke(Object proxy, Method m, Object[] args) {  
42.        Object result = null;  
43.        try {  
44.            /** 
45.             * 動態代理類$Proxy0呼叫xiangQin方法時會呼叫它自己的xiangQin方法, 
46.             * 而它自己的xiangQin方法裡面呼叫的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法, 
47.             * 也就是ReadyInvocationHandler類的invoke方法。 
48.             * 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實際上就是動態代理類$Proxy0, 
49.             * 如果你將其強轉成XiangQinInterface然後呼叫它的xiangQin方法,然後它就會呼叫super.h.invoke(this, , ),這樣就會死迴圈。 
50.             */  
51.            /** 
52.             * 網上關於這裡最多問題就是Object proxy放在這裡用來做什麼呢?這個我也不知道, 
53.             * 不過至少我們知道它到底是個什麼東西,具體做什麼用嘛就不得而知了 
54.             */  
55.            System.out.println(proxy.getClass().getSimpleName());  
56.            System.out.println("張三相親前,代理人給他打扮了打扮。");  
57.            result = m.invoke(zhangSan, args);  
58.        } catch (Exception ex) {  
59.            System.exit(1);  
60.        }  
61.        return result;  
62.    }  
63.}  
64.import java.lang.reflect.InvocationHandler;  
65.import java.lang.reflect.Method;  
66.import java.lang.reflect.Proxy;  
67.  
68./** 
69. * 張三來到了婚介所(相親現場),開始相親。 
70. *  
71. * @author zhengt 
72. * @time Jun 3, 2095 3:17:16 PM 
73. */  
74.public class HunJieSuo {  
75.    public static void main(String args[]) {  
76.        //先將張三相親這個相親的實現類例項化,也就是得到XiangQinInterface介面的一個例項物件  
77.        XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl();  
78.        /** 
79.         * 得到ZhangSanXiangQinInterfaceImpl這個類的一個代理類,同時為代理類綁定了一個處理類ReadyInvocationHandler。 
80.         * 聽著很繞口,其實就是每次呼叫ZhangSanXiangQinInterfaceImpl這個子類的xiangQin方法時, 
81.         * 不是zhangSan這個ZhangSanXiangQinInterfaceImpl類的例項去呼叫, 
82.         * 而是這個ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去呼叫它自己的invoke方法, 
83.         * 這個invoke方法裡呢可以呼叫zhangSan這個例項的xiangQin方法 
84.         */  
85.        /** 
86.         * 在java種怎樣實現動態代理呢 
87.         * 第一步,我們要有一個介面,還要有一個介面的實現類,而這個實現類呢就是我們要代理的物件, 
88.         * 所謂代理呢也就是在呼叫實現類的方法時,可以在方法執行前後做額外的工作,這個就是代理。 
89.         * 第二步,我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler介面, 
90.         * 為什麼要繼承它呢?因為代理類的例項在呼叫實現類的方法的時候,不會調真正的實現類的這個方法, 
91.         * 而是轉而呼叫這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以呼叫真正的實現類的這個方法。 
92.         * 第三步,在要用代理類的例項去呼叫實現類的方法的時候,寫出下面兩段程式碼。 
93.         */  
94.        XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(  
95.                zhangSan.getClass().getClassLoader(),  
96.                zhangSan.getClass().getInterfaces(),  
97.                new ReadyInvocationHandler(zhangSan));  
98.        proxy.xiangQin();  
99.        /** 
100.         * 這裡要解釋下中部那段長長的程式碼的意思,以及具體做了哪些工作? 
101.         * 第一,根據zhangSan.getClass().getClassLoader()這個要代理類的類載入器和 
102.         * zhangSan.getClass().getInterfaces()要代理類所實現的所有的介面 
103.         * 作為引數呼叫Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces) 
104.         * 的方法返回代理類的java.lang.Class物件,也就是得到了java動態生成的代理類$Proxy0的Class物件。 
105.         * 同時,java還讓這個動態生成的$Proxy0類實現了要代理類的實現的所有介面,並繼承了Proxy介面。 
106.         * 第二,例項化這個動態生成的$Proxy0類的一個例項,例項化代理類的建構函式為Proxy(InvocationHandler h), 
107.         * 也就是說要例項化這個動態生成的$Proxy0類,必須給它一個InvocationHandler引數,也就是我們自己實現的用來在代理類 
108.         * 方法執行前後做額外工作的類ReadyInvocationHandler。 
109.         * 這段程式碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan)) 
110.         * 得到的其實是一個類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。 
111.         * 第三,將這個$Proxy0類強制轉型成XiangQinInterface型別,呼叫xiangQin方法。 
112.         */  
113.    }  
114.}