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

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

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

    posts - 0,  comments - 6,  trackbacks - 0

    代理模式的定義

        代理模式用于為某一個對象提供一個替身(一個代理對象),并通過這個替身控制客戶代碼對這個對象的訪問。代理模式屬于對象的結(jié)構(gòu)模式。

        下面是一些使用代理模式的場合:

    用遠程代理控制訪問遠程對象

    虛擬代理控制訪問創(chuàng)建開銷大的資源對象

    保護代理基于權(quán)限控制對資源的訪問


        首先,讓我們來看一下代理模式的結(jié)構(gòu)類圖:


    代理模式簡單例子

    業(yè)務(wù)接口

    public interface IHello {

    /** 假設(shè)這是一個業(yè)務(wù)方法*/

    void sayHello(String name);

    }

    業(yè)務(wù)實現(xiàn)類

    public class Hello implements IHello {

        public void sayHello(String name) {

            System.out.println("Hello " + name);

        }

        public static void main(String[] args) {

         IHello hello = new Hello();

    hello.sayHello("鄭州蜂鳥科技");

    }

    }

    運行輸出:Hello 鄭州蜂鳥科技

        接下來,我們希望對所有該業(yè)務(wù)方法進行性能測試,即計算業(yè)務(wù)方法執(zhí)行消耗的時間。要求不能修改原來的代碼,但是可以擴展新的類。也就是要滿足面向?qū)ο笤O(shè)計原則:開閉原則(對擴展開放,對修改關(guān)閉)。

    public class StaticHelloProxy implements IHello {

        private IHello hello;

     

        public StaticHelloProxy(IHello hello) {

             this.hello = hello;

        }

     

        public void sayHello(String name) {

         long start = System.currentTimeMillis();

            System.out.println("sayHello method start time:"+start);

            hello.sayHello(name);

            long end = System.currentTimeMillis();

            System.out.println("sayHello method end time:"+end);

            System.out.println("Total time:"+(end - start));

        }

        

        public static void main(String[] args) {

    IHello hello = new StaticHelloProxy(new Hello());

    hello.sayHello("鄭州蜂鳥科技");

    }

    }

    輸出結(jié)果:

    sayHello method start time:1290077898984

    Hello 鄭州蜂鳥科技

    sayHello method end time:1290077898984

    Total time:0

        以上代理模式只是概念上的設(shè)計和實現(xiàn),實用性比較差。它有很多問題,比如,我們有很多不同業(yè)務(wù)類的不同業(yè)務(wù)方法都需要進行性能測試,那么我們就需要些很多代理類,并為每個代理類設(shè)計很多方法。這簡直是類和方法的爆炸。解決這一問題的方案是動態(tài)代理技術(shù)。

    動態(tài)代理模式

    針對接口的動態(tài)代理:JDK對動態(tài)代理模式的支持

        Java 在 java.lang.reflect 包中有自己對代理模式的支持,你可以在運行時動態(tài)創(chuàng)建一個代理類,實現(xiàn)一個或多個接口,并將方法的調(diào)用轉(zhuǎn)發(fā)到你所指定的類,我們稱之為動態(tài)代理。請看結(jié)構(gòu)類圖:


    Hello創(chuàng)建動態(tài)代理,而且它可以為任何實現(xiàn)了接口的類型創(chuàng)建代理:

    public class DynamicJdkProxy implements InvocationHandler {

    private Object proxyobj;

    public DynamicJdkProxy(Object obj) {

    proxyobj = obj;

    }

    public static Object factory(Object obj) {

    Class cls = obj.getClass();

    return Proxy.newProxyInstance(

    cls.getClassLoader(),//加載目標對象類型的類加載器

    cls.getInterfaces(), //目標對象類型實現(xiàn)的接口

    new DynamicJdkProxy(obj));//代理對象

    }

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

    throws Throwable {

            System.out.println(proxy.getClass());

    long start = System.currentTimeMillis();

            System.out.println("sayHello method start time:"+start);

    if (args != null) {

    for (int i = 0; i < args.length; i++) {

    System.out.println(args[i] + "");

    }

    }

    Object o = method.invoke(proxyobj, args);

    long end = System.currentTimeMillis();

            System.out.println("sayHello method end time:"+end);

            System.out.println("Total time:"+(end - start));

    return o;

    }

    }

    測試代碼:

    public static void main(String[] args) {

    IHello hello = (IHello) DynamicJdkProxy.factory(new Hello());

    hello.sayHello("蜂鳥科技");

    }

    執(zhí)行結(jié)果:

    class $Proxy0

    sayHello method start time:1284427181218

    蜂鳥科技

    Hello 蜂鳥科技

    sayHello method end time:1284427181265

    Total time:47

        使用JDK創(chuàng)建代理有一個限制,即它只能為接口創(chuàng)建代理,這一點我們從Proxy的接口方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)就看得很清楚,第三個入?yún)?/font>interfaces就是為代理實例指定的實現(xiàn)接口。雖然,面向接口的編程被很多很有影響力人(包括Rod Johnson)的推崇,但在實際開發(fā)中,開發(fā)者也遇到了很多困惑:難道對一個簡單業(yè)務(wù)表的操作真的需要創(chuàng)建5個類(領(lǐng)域?qū)ο箢悺?/font>Dao接口,Dao實現(xiàn)類,Service接口和Service實現(xiàn)類)嗎?對于這一問題,我們還是留待大家進一步討論。現(xiàn)在的問題是:對于沒有通過接口定義業(yè)務(wù)方法的類,如何動態(tài)創(chuàng)建代理實例呢?JDK的代理技術(shù)顯然已經(jīng)黔驢技窮,CGLib作為一個替代者,填補了這個空缺。你可以從http://cglib.sourceforge.net/獲取CGLib的類包,也可以直接從Spring的關(guān)聯(lián)類庫lib/cglib中獲取類包。

    針對類的動態(tài)代理:CGLIB動態(tài)代理庫

        CGLib采用非常底層的字節(jié)碼技術(shù),可以為一個類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,并在攔截方法相應(yīng)地織入橫切邏輯。下面,我們采用CGLib技術(shù),編寫一個可以為任何類創(chuàng)建織入性能監(jiān)視橫切邏輯的代理對象的代理器,如代碼所示:

    public class DynamicCglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {

    enhancer.setSuperclass(clazz);// ① 設(shè)置需要創(chuàng)建子類的類

    enhancer.setCallback(this);

    return enhancer.create(); // ②通過字節(jié)碼技術(shù)動態(tài)創(chuàng)建子類實例

    }

    public Object intercept(Object obj, Method method, Object[] args,

    MethodProxy proxy) throws Throwable {

        System.out.println(obj.class);//看看動態(tài)生成的對象的類型;

    long start = System.currentTimeMillis();

            System.out.println("sayHello method start time:"+start);

            

    Object result = proxy.invokeSuper(obj, args); // ③ 通過代理類調(diào)用父類中的方法

    long end = System.currentTimeMillis();

    System.out.println("sayHello method end time:"+end);

            System.out.println("Total time:"+(end - start));

    return result;

    }

    }

    在上面代碼中,你可以通過getProxy(Class clazz)為一個類創(chuàng)建動態(tài)代理對象,該代理對象是指定類clazz的子類。在這個代理對象中,我們織入性能監(jiān)視的橫切邏輯(粗體部分)。intercept(Object obj, Method method, Object[] args,MethodProxy proxy)CGLib定義的Inerceptor接口的方法,obj表示父類的實例,method為父類方法的反射對象,args為方法的動態(tài)入?yún)ⅲ?/font>proxy為代理類實例。

    下面,我們通過CglibProxyForumServiceImpl類創(chuàng)建代理對象,并測試代理對象的方法,如代碼所示:

    public static void main(String[] args) {

    DynamicCglibProxy proxy = new DynamicCglibProxy();

    Hello h = (Hello) proxy.getProxy(Hello.class);

    h.sayHello("蜂鳥科技");

    }

    執(zhí)行結(jié)果:

    class com.ntcsoft.proxy.noproxy.Hello$$EnhancerByCGLIB$$127f0ad5

    sayHello method start time:1284427305921

    Hello 蜂鳥科技

    sayHello method end time:1284427305968

    Total time:47

    到這里我們簡單掌握了代理模式。動態(tài)代理在struts2、hibernate和spring中都大量使用到了,這將對我們理解這些框架有很大意義。有時間我們來模擬實現(xiàn)這些框架的部分功能。

    學軟件開發(fā),到蜂鳥科技!
    超強的師資力量 、完善的課程體系 、超低的培訓價格 、真實的企業(yè)項目。

    網(wǎng)址:www.ntcsoft.com 
    電話:0371-63839606 
    鄭州軟件開發(fā)興趣小組群:38236716

    posted on 2010-11-26 01:01 whistler 閱讀(429) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    留言簿(2)

    我參與的團隊

    文章檔案(22)

    搜索

    •  

    最新評論

    主站蜘蛛池模板: 免费观看激色视频网站(性色)| 亚洲成年人啊啊aa在线观看| 欧洲亚洲国产精华液| 国产成A人亚洲精V品无码性色| 青青草国产免费久久久下载 | 青青青青青青久久久免费观看| 日本亚洲免费无线码| 最近2019中文免费字幕在线观看| 亚洲精品国产摄像头| 18亚洲男同志videos网站| 亚洲综合国产精品第一页| 成人免费福利电影| 久久成人a毛片免费观看网站| 免费又黄又爽又猛大片午夜| 亚洲日韩中文字幕无码一区| 久久精品国产亚洲AV无码麻豆 | 99视频免费观看| h在线看免费视频网站男男| 亚洲一区二区观看播放| 亚洲综合激情九月婷婷| 亚洲AV无码AV男人的天堂| 色噜噜AV亚洲色一区二区| 亚洲A∨午夜成人片精品网站| 拍拍拍又黄又爽无挡视频免费| 精品国产麻豆免费网站| 亚洲国产91精品无码专区| 国产亚洲情侣一区二区无| 免费v片在线观看无遮挡| 午夜私人影院免费体验区| 精品福利一区二区三区免费视频 | 亚在线观看免费视频入口| 国产成人自产拍免费视频| 爱丫爱丫影院在线观看免费| 亚洲免费在线视频| 欧亚精品一区三区免费| 久久久高清免费视频 | 无码午夜成人1000部免费视频| xxxx日本免费| 国产小视频在线观看免费| 国产成人3p视频免费观看| 亚洲日韩精品一区二区三区 |