<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    代理模式

    1. 代理模式

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

    代理模式一般涉及到的角色有:

    抽象角色:聲明真實對象和代理對象的共同接口;

    代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝。

    真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。(參見文獻1)

    以下以《Java與模式》中的示例為例:

    抽象角色:

    abstract public class Subject

    {

    abstract public void request();

    }

    真實角色:實現了Subject的request()方法。

    public class RealSubject extends Subject

    {

    public RealSubject()

    {

    }



    public void request()

    {

    System.out.println("From real subject.");

    }

    }

    代理角色:

    public class ProxySubject extends Subject

    {

    private RealSubject realSubject; //以真實角色作為代理角色的屬性



    public ProxySubject()

    {

    }



    public void request() //該方法封裝了真實對象的request方法

    {

    preRequest();

    if( realSubject == null )

    {

    realSubject = new RealSubject();

    }

    realSubject.request(); //此處執行真實對象的request方法

    postRequest();

    }



    private void preRequest()

    {

    //something you want to do before requesting

    }



    private void postRequest()

    {

    //something you want to do after requesting

    }

    }

    客戶端調用:

    Subject sub=new ProxySubject();

    Sub.request();

    由以上代碼可以看出,客戶實際需要調用的是RealSubject類的request()方法,現在用ProxySubject來代理 RealSubject類,同樣達到目的,同時還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。

    另外,如果要按照上述的方法使用代理模式,那么真實角色必須是事先已經存在的,并將其作為代理對象的內部屬性。但是實際使用時,一個真實角色必須對應一個代理角色,如果大量使用會導致類的急劇膨脹;此外,如果事先并不知道真實角色,該如何使用代理呢?這個問題可以通過Java的動態代理類來解決。



    2.動態代理類

    Java動態代理類位于Java.lang.reflect包下,一般主要涉及到以下兩個類:

    (1). Interface InvocationHandler:該接口中僅定義了一個方法Object:invoke(Object obj,Method method, Object[] args)。在實際使用時,第一個參數obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數數組。這個抽象方法在代理類中動態實現。


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

    Protected Proxy(InvocationHandler h):構造函數,估計用于給內部的h賦值。

    Static Class getProxyClass (ClassLoader loader, Class[] interfaces):獲得一個代理類,其中loader是類裝載器,interfaces是真實類所擁有的全部接口的數組。

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



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

    在使用動態代理類時,我們必須實現InvocationHandler接口,以第一節中的示例為例:

    抽象角色(之前是抽象類,此處應改為接口):

    public interface Subject

    {

    abstract public void request();

    }

    具體角色RealSubject:同上;



    代理角色:

    import java.lang.reflect.Method;

    import java.lang.reflect.InvocationHandler;



    public class DynamicSubject implements InvocationHandler {

    private Object sub;



    public DynamicSubject() {

    }



    public DynamicSubject(Object obj) {

    sub = obj;

    }





    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    System.out.println("before calling " + method);



    method.invoke(sub,args);



    System.out.println("after calling " + method);

    return null;

    }



    }



    該代理類的內部屬性為Object類,實際使用時通過該類的構造函數DynamicSubject(Object obj)對其賦值;此外,在該類還實現了invoke方法,該方法中的

    method.invoke(sub,args);

    其實就是調用被代理對象的將要被執行的方法,方法參數sub是實際的被代理對象,args為執行被代理對象相應操作所需的參數。通過動態代理類,我們可以在調用之前或之后執行一些相關操作。

    客戶端:

    import java.lang.reflect.InvocationHandler;

    import java.lang.reflect.Proxy;

    import java.lang.reflect.Constructor;

    import java.lang.reflect.Method;



    public class Client

    {



    static public void main(String[] args) throws Throwable

    {

    RealSubject rs = new RealSubject(); //在這里指定被代理類

    InvocationHandler ds = new DynamicSubject(rs); //初始化代理類

    Class cls = rs.getClass();

    //以下是分解步驟

    /*

    Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ;

    Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});

    Subject subject =(Subject) ct.newInstance(new Object[]{ds});

    */

    //以下是一次性生成

    Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),

    cls.getInterfaces(),ds );



    subject.request();

    }

    通過這種方式,被代理的對象(RealSubject)可以在運行時動態改變,需要控制的接口(Subject接口)可以在運行時改變,控制的方式(DynamicSubject類)也可以動態改變,從而實現了非常靈活的動態代理關系(參見文獻2)。
     
     
     

    對于面向接口編程的項目免不了要一反射相接觸,動態得到實例:
    public interface a {
     public void sayHello();
    }
    ---------------------------
    第一種情況是當
    aImpl實現類為默認的構造方法:
    根據類名aImpl動態得到實例
    Class c=Class.forName("aImpl");
    a instance=(a)c.newInstance();
    a.sayHello();
    ------------
    第二種情況當
    aImpl為帶參數的構造方法時:
    Class o=Class.forName("aImpl");//aImpl為要實例化的例名,可以從配置文件當中獲取
       Constructor cous = null;
       cous=o.getConstructor(new Class[]{String.class});//構造器的參數類型
       a ao=(a) cous.newInstance(new Object[]{"xxx"});//"xxx為傳入的參數值
       ao.sayHello();
    第三種就是構造器為私有的時候,我們通過方法獲取實例getInstance()(自己定的)
    Class o=Class.forName("aImpl");
       Method method=o.getMethod("getInstance",new Class[]{String.class});
    //getInstance為返回為aImpl實例的方法名
        a ao=(a) method.invoke(null,new Object[]{"xxx"});//注意了前面的參數為null,是有
    //條件的,就是要求getInstance為static類型的,我想大家都會這樣設計的
           ao.sayHello();
    做連接池的話,一種方式就是使用動態代理類,當Connection調用close()方法時,我們可以利用方法攔截器,在調用close方法的時候把連接放到緩存里面去,供以后再次利用..
    a ao=(a)Proxy.newProxyInstance(aImpl.class.getClassLoader(),aImpl.class.getInterfaces(),
         new InvocationHandler()
         {

          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           Object re=null;
           System.out.println("before--------"+method.getName());
    //在這里我們添加自己的一些處理方法,如把連接放到緩存去撒!
           //re=method.invoke(new aImpl(),args);
           return re;
          }
        
         });
       ao.sayHello();

    posted on 2007-04-02 14:06 leoli 閱讀(266) 評論(0)  編輯  收藏 所屬分類: java

    導航

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統計

    常用鏈接

    留言簿(6)

    隨筆分類

    隨筆檔案(17)

    文章分類(86)

    收藏夾(3)

    flex blog

    good site

    java blog

    my friend

    tools

    抓蝦

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲国产视频网站| 亚洲一区二区三区高清| 亚洲熟妇无码av另类vr影视| 色欲色香天天天综合网站免费 | 亚洲人成无码网站在线观看| 999久久久免费精品播放| 亚洲日韩乱码中文无码蜜桃| 在线观看H网址免费入口| 亚洲免费人成视频观看| 成人影片麻豆国产影片免费观看| 国产亚洲精aa在线看| 曰皮全部过程视频免费国产30分钟| 亚洲av纯肉无码精品动漫| 日韩免费一区二区三区| 免费看一级一级人妻片| 久久亚洲国产精品123区| 中文字幕无码一区二区免费| 亚洲综合一区二区精品导航| 精品国产污污免费网站aⅴ| 在线观看亚洲AV日韩A∨| 亚洲阿v天堂在线2017免费| 97在线免费观看视频| 久久久久亚洲AV无码专区体验| 永久看日本大片免费35分钟| 亚洲成年网站在线观看| 亚洲精品高清一二区久久| 免费观看91视频| 亚洲三级在线观看| 亚洲高清偷拍一区二区三区 | 永久免费毛片在线播放| 国产亚洲高清在线精品不卡| 久久亚洲国产午夜精品理论片| 一级毛片**不卡免费播| 亚洲AV日韩AV无码污污网站| 亚洲色精品vr一区二区三区| 无码国产精品一区二区免费式直播 | 亚洲一区二区在线视频| 免费无码又爽又刺激聊天APP| 激情婷婷成人亚洲综合| 亚洲国产精品成人精品无码区在线| 免费可以在线看A∨网站|