一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

java反射機制與動態(tài)代理(三)...

 碧海山城 2009-11-26

本文講述代理模式...

代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。
在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

 

代理模式一般涉及到的角色有:
  抽象角色:聲明真實對象和代理對象的共同接口;
  代理角色:代理對象角色內(nèi)部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執(zhí)行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝;
  真實角色:代理角色所代表的真實對象,是我們最終要引用的對象;

 

下面四個類講述一個簡單的靜態(tài)代理,參見程序Subject.java,RealSubject.java,ProxySubject.java和Client.java。把他們放在一個包下即可,代碼如下:

Subject.java代碼 復制代碼
  1. abstract public class Subject{      
  2.           
  3.     abstract public void request();      
  4. }   

 

Realsubject.java代碼 復制代碼
  1. public class RealSubject extends Subject      
  2. {      
  3.     public void request()      
  4.     {      
  5.         System.out.println("From real subject.");      
  6.     }      
  7. }  

 

Proxysubject.java代碼 復制代碼
  1. public class ProxySubject extends Subject{      
  2.           
  3.     private RealSubject realSubject; // 以真實角色作為代理角色的屬性      
  4.      
  5.     public void request() // 該方法封裝了真實對象的request方法      
  6.     {      
  7.         preRequest();      
  8.      
  9.         if (realSubject == null) {      
  10.             realSubject = new RealSubject();      
  11.         }      
  12.      
  13.         realSubject.request(); // 此處執(zhí)行真實對象的request方法      
  14.      
  15.         postRequest();      
  16.     }      
  17.      
  18.     private void preRequest() {      
  19.      
  20.         System.out.println("先前做的事情");      
  21.     }      
  22.      
  23.     private void postRequest() {      
  24.      
  25.         System.out.println("之后做的事情");      
  26.     }      
  27. }  

 

Client.java代碼 復制代碼
  1. public class Client{      
  2.     public static void main(String[] args)      
  3.     {      
  4.         Subject sub = new ProxySubject();      
  5.      
  6.         sub.request();      
  7.     }      
  8. }  

 

要有四個角色:抽象角色,代理角色,真實角色和客戶。在Java中要想對其他對象引用,生成一個那個對象的屬性就行了。比如本例中就是在ProxySubject類中聲明了RealSubject類的對象,作為一個屬性存在ProxySubject中。

 

由以上代碼可以看出,客戶實際需要調(diào)用的是RealSubject類的request()方法,現(xiàn)在用ProxySubject來代理 RealSubject類,同樣達到目的,同時還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。
 
另外,如果要按照上述的方法使用代理模式,那么真實角色必須是事先已經(jīng)存在的,并將其作為代理對象的內(nèi)部屬性。但是實際使用時,一個真實角色必須對應一個 代理角色,如果大量使用會導致類的急劇膨脹;此外,如果事先并不知道真實角色,該如何使用代理呢?這個問題可以通過Java的動態(tài)代理類來解決。

 

下面講述動態(tài)代理。

 

Java動態(tài)代理類位于java.lang.reflect包下,一般主要涉及到以下兩個類(接口算作特殊類):


(1)Interface InvocationHandler:該接口中僅定義了一個方法

 

public object invoke(Object obj,Method method, Object[] args)


在實際使用時,第一個參數(shù)obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數(shù)數(shù)組。 這個抽象方法在代理類中動態(tài)實現(xiàn)。

 

(2)Proxy:該類即為動態(tài)代理類,作用類似于上例中的ProxySubject,其中主要包含以下內(nèi)容:

 

protected Proxy(InvocationHandler h):構(gòu)造函數(shù),用于給內(nèi)部的h賦值;

 

static Class getProxyClass (ClassLoader loader, Class[] interfaces):獲得一個代理類,其中l(wèi)oader是類裝載器,interfaces是真實類所擁有的全部接口的數(shù)組;

 

static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例,返回后的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)。

 

所謂Dynamic Proxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,然后該class就宣稱它實現(xiàn)了這些 interface。你當然可以把該class的實例當作這些interface中的任何一個來用。當然,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質(zhì)性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。

 

下面例子講述了一個動態(tài)代理Subject.java,RealSubject.java,DynamicSubject.java和Client.java,把他們放在一個包下,代碼如下:

Subject.java代碼 復制代碼
  1. //抽象角色(之前是抽象類,此處應改為接口)      
  2. public interface Subject      
  3. {      
  4.     public void request();      
  5. }  

 

Realsubject.java代碼 復制代碼
  1. //具體角色      
  2. public class RealSubject implements Subject      
  3. {      
  4.      
  5.     public RealSubject()      
  6.     {      
  7.     }      
  8.      
  9.     public void request()      
  10.     {      
  11.         System.out.println("真正做事的。");      
  12.     }      
  13. }  

 

Dynamicsubject.java代碼 復制代碼
  1. //代理處理器      
  2. /**     
  3.  * 該代理類的內(nèi)部屬性為Object類,實際使用時通過該類的構(gòu)造函數(shù)DynamicSubject(Object obj)對其賦值;     
  4.  * 此外,在該類還實現(xiàn)了invoke方法,該方法中的 method.invoke(sub,args);     
  5.  * 其實就是調(diào)用被代理對象的將要被執(zhí)行的方法,方法參數(shù)sub是實際的被代理對象,     
  6.  * args為執(zhí)行被代理對象相應操作所需的參數(shù)。     
  7.  * 通過動態(tài)代理類,我們可以在調(diào)用之前或之后執(zhí)行一些相關(guān)操作     
  8.  */     
  9.      
  10. public class DynamicSubject implements InvocationHandler      
  11. {      
  12.     private Object sub;      
  13.      
  14.     public DynamicSubject()      
  15.     {      
  16.     }      
  17.      
  18.     public DynamicSubject(Object obj)      
  19.     {      
  20.         sub = obj;      
  21.     }      
  22.      
  23.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable      
  24.     {      
  25.         System.out.println("調(diào)用前" + method);      
  26.      
  27.         method.invoke(sub, args);      
  28.      
  29.         System.out.println("調(diào)用后 " + method);      
  30.      
  31.         return null;      
  32.     }      
  33. }   

 

Client.java代碼 復制代碼
  1. //客戶端      
  2. public class Client      
  3. {      
  4.     static public void main(String[] args) throws Throwable      
  5.     {      
  6.      
  7.         RealSubject rs = new RealSubject(); // 在這里指定被代理類      
  8.         InvocationHandler ds = new DynamicSubject(rs);      
  9.         Class<?> cls = rs.getClass();      
  10.      
  11.         // 以下是一次性生成代理      
  12.      
  13.         Subject subject = (Subject) Proxy.newProxyInstance(      
  14.                 cls.getClassLoader(), cls.getInterfaces(), ds);      
  15.      
  16.         subject.request();      
  17.     }      
  18. }  

 

這個程序中把靜態(tài)代理類的抽象類改變?yōu)橐粋€接口,而實際類實現(xiàn)這個接口。是因為Proxy類的newProxyInstance方法傳入需要提供一個接口,這個是Java動態(tài)代理框架給我們設(shè)計好的了。本例的ProxySubject類實現(xiàn)了InvocationHandler接口及實現(xiàn)invoke方法,并且提供一個帶參數(shù)的構(gòu)造方法,通過Client類動態(tài)的調(diào)用真實類。

 

 Client類通過DynamicSubject類生成真實類的代理對象,并經(jīng)由Proxy類的newProxyInstance方法實現(xiàn)生成“一個能做真實類做的事的代理”,并由該代理直接調(diào)用真實類所具有的方法。

 

 OK,也許還會有些迷惑,不過不要緊,沒有什么高端的知識能夠一次就成功的,要勤于練習。

 

下面這個類作為參考,代碼如下:

Vectorproxy.java代碼 復制代碼
  1. import java.lang.reflect.InvocationHandler;      
  2. import java.lang.reflect.Method;      
  3. import java.lang.reflect.Proxy;      
  4. import java.util.List;      
  5. import java.util.Vector;      
  6.      
  7. public class VectorProxy implements InvocationHandler      
  8. {      
  9.     private Object proxyobj;      
  10.      
  11.     public VectorProxy(Object obj)      
  12.     {      
  13.         proxyobj = obj;      
  14.     }      
  15.      
  16.     public static Object factory(Object obj)      
  17.     {      
  18.         Class<?> cls = obj.getClass();      
  19.      
  20.         return Proxy.newProxyInstance(cls.getClassLoader(),      
  21.                 cls.getInterfaces(), new VectorProxy(obj));      
  22.     }      
  23.      
  24.     public Object invoke(Object proxy, Method method, Object[] args)      
  25.             throws Throwable      
  26.     {      
  27.         System.out.println("before calling " + method);      
  28.      
  29.         if (args != null)      
  30.         {      
  31.             for (int i = 0; i < args.length; i++)      
  32.             {      
  33.                 System.out.println(args[i] + "");      
  34.             }      
  35.         }      
  36.         Object object = method.invoke(proxyobj, args);      
  37.      
  38.         System.out.println("after calling " + method);      
  39.         return object;      
  40.     }      
  41.      
  42.     @SuppressWarnings("unchecked")      
  43.     public static void main(String[] args)      
  44.     {      
  45.         List<String> v = (List<String>) factory(new Vector<String>(10));      
  46.      
  47.         v.add("New");      
  48.         v.add("York");      
  49.         System.out.println(v);      
  50.      
  51.         v.remove(0);      
  52.         System.out.println(v);      
  53.     }      
  54. }  

 

這個類看不明白不要緊,慢慢來。

 

下面也是一個演示程序,作為擴展知識用,一共五個類,在同一包下,代碼如下:

 

 五個類Foo.java, FooImpl.java, FooImpl2.java, CommonInvocationHandler.java和Demo.java。

Foo.java代碼 復制代碼
  1. public interface Foo      
  2. {      
  3.     void doAction();      
  4. }   

 

Fooimpl.java代碼 復制代碼
  1. public class FooImpl implements Foo      
  2. {      
  3.     public FooImpl()      
  4.     {      
  5.     }      
  6.      
  7.     public void doAction()      
  8.     {      
  9.         System.out.println("in FooImp1.doAction()");      
  10.     }      
  11. }   

 

Fooimpl2.java代碼 復制代碼
  1. public class FooImpl2 implements Foo      
  2. {      
  3.     public FooImpl2()      
  4.     {      
  5.     }      
  6.      
  7.     public void doAction()      
  8.     {      
  9.         System.out.println("in FooImp2.doAction()");      
  10.     }      
  11. }  

 

Commoninvocationhandler.java代碼 復制代碼
  1. import java.lang.reflect.InvocationHandler;      
  2. import java.lang.reflect.Method;      
  3.      
  4. public class CommonInvocationHandler implements InvocationHandler      
  5. {      
  6.      
  7.     // 動態(tài)執(zhí)行對象,需要回調(diào)的對象      
  8.     private Object target;      
  9.      
  10.     // 支持構(gòu)造子注射      
  11.     public CommonInvocationHandler()      
  12.     {      
  13.      
  14.     }      
  15.      
  16.     // 支持構(gòu)造子注射      
  17.     public CommonInvocationHandler(Object target)      
  18.     {      
  19.         setTarget(target);      
  20.     }      
  21.      
  22.     /**     
  23.      *      
  24.      * 采用setter方法注射     
  25.      *      
  26.      * @param target     
  27.      *      
  28.      */     
  29.     public void setTarget(Object target)      
  30.     {      
  31.         this.target = target;      
  32.     }      
  33.      
  34.     /**     
  35.      *      
  36.      * 調(diào)用proxy中指定的方法method,并傳入?yún)?shù)列表args     
  37.      *      
  38.      * @param proxy     
  39.      *            代理類的類型,例如定義對應method的代理接口     
  40.      *      
  41.      * @param method     
  42.      *            被代理的方法     
  43.      *      
  44.      * @param args     
  45.      *            調(diào)用被代理方法的參數(shù)     
  46.      *      
  47.      * @return     
  48.      *      
  49.      * @throws java.lang.Throwable     
  50.      *      
  51.      */     
  52.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable      
  53.     {      
  54.         return method.invoke(target, args);      
  55.     }      
  56. }  

 

Demo.java代碼 復制代碼
  1. import java.lang.reflect.Proxy;      
  2.      
  3. public class Demo      
  4. {      
  5.     public static void main(String[] args)      
  6.     {      
  7.      
  8.         // 1.通用的動態(tài)代理實現(xiàn)      
  9.      
  10.         CommonInvocationHandler handler = new CommonInvocationHandler();      
  11.      
  12.         Foo f;      
  13.      
  14.         // 2.接口實現(xiàn)1      
  15.      
  16.         handler.setTarget(new FooImpl());      
  17.      
  18.         // 方法參數(shù)說明:代理類、代理類實現(xiàn)的接口列表、代理類的處理器      
  19.      
  20.         // 關(guān)聯(lián)代理類、代理類中接口方法、處理器,當代理類中接口方法被調(diào)用時,會自動分發(fā)到處理器的invoke方法      
  21.      
  22.         // 如果代理類沒有實現(xiàn)指定接口列表,會拋出非法參數(shù)異常      
  23.      
  24.         f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),      
  25.      
  26.         new Class[] { Foo.class },      
  27.      
  28.         handler);      
  29.      
  30.         f.doAction();      
  31.      
  32.         // 3.接口實現(xiàn)2      
  33.      
  34.         handler.setTarget(new FooImpl2());      
  35.      
  36.         f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),      
  37.      
  38.         new Class[] { Foo.class },      
  39.      
  40.         handler);      
  41.      
  42.         f.doAction();      
  43.     }      
  44. }  

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产超碰在线观看免费| 亚洲男人的天堂色偷偷| 色综合久久超碰色婷婷| 六月丁香六月综合缴情| 亚洲精品国产主播一区| 婷婷一区二区三区四区| 日韩欧美三级中文字幕| 欧美日韩国产另类一区二区| 亚洲精品福利入口在线| 国产精品成人一区二区三区夜夜夜| 九九热这里有精品20| 日韩欧美91在线视频| 日韩欧美一区二区不卡视频| 亚洲中文字幕剧情在线播放| 国产精品一区二区传媒蜜臀| 色综合久久六月婷婷中文字幕| 欧美日韩校园春色激情偷拍 | 久久福利视频视频一区二区| 一区二区三区四区亚洲另类| 99热九九热这里只有精品| 厕所偷拍一区二区三区视频| 成人精品视频在线观看不卡| 亚洲中文字幕在线视频频道| 果冻传媒精选麻豆白晶晶| 欧美日韩黑人免费观看| 香港国产三级久久精品三级| 91国内视频一区二区三区| 国产成人午夜在线视频| 欧美日韩一区二区三区色拉拉| 久久精品亚洲精品国产欧美| 亚洲免费观看一区二区三区| 国产剧情欧美日韩中文在线| 婷婷一区二区三区四区| 有坂深雪中文字幕亚洲中文 | 亚洲综合天堂一二三区| 日韩精品在线观看一区| 亚洲一区二区三区有码| 亚洲av日韩av高潮无打码| 亚洲中文字幕人妻av| 国产亚洲系列91精品| 亚洲av熟女国产一区二区三区站|