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

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

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

    walterwing  
    日歷
    <2008年7月>
    293012345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789
    統計
    • 隨筆 - 12
    • 文章 - 1
    • 評論 - 7
    • 引用 - 0

    導航

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

     
    今天讀了讀夏昕寫的《Spring開發指南》,在“AOP in Spring”一節,作者講述了Spring中如何通過動態AOP來提供內置的AOP支持。“從技術角度來講,所謂動態AOP,即通過動態Proxy模式,在目標對象的方法調用前后插入相應的處理代碼”

    作者舉了一些例子來解釋何為靜態Proxy,何為動態Proxy。奈何我根基尚淺,最作者舉的動態Proxy的例子懵懂不解,于是自己嘗試著摸索一番,終于對動態Proxy的用法有了一個初步的認識。

    首先還是來看靜態Proxy,就我目前的認識看來,Proxy的主要用途是對類中方法的執行進行一下包裝,在方法執行之前,或之后,或both,加入一些“額外”的操作。典型的應用就是加入事務處理。

    靜態Proxy相對來講比較簡單,它是對上面所述思想的一個最直接的實現。

    假設我們現在有如下一個接口:

    package aop;

    public interface Foo {
        
    public String getMessage(String arg);
    }

    以及該接口的一個實現類:

    package aop;

    public class FooImpl implements Foo {

        
    public String getMessage(String arg) {
            
    return "hi " + arg;
        }


    }


    那么很容易,我們可以通過如下方式進行調用:

    package aop;

    public class Test {

        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            Foo foo 
    = new FooImpl();
            String message 
    = foo.getMessage("Wing");
            System.out.println(message);
        }


    }


    輸出結果:
    hi Wing


    現在問題來了:如果現在我們想在getMessage()之外添加一些額外的操作,比如在這之前輸出“Begin”,在之后輸出“done”,但又不能改變原有接口,怎么辦?也很簡單,用靜態Proxy就可以很方便的實現:

    package aop;

    public class StaticProxy implements Foo {
        
    private Foo foo;
        
        
    public StaticProxy(Foo foo) {
            
    this.foo = foo;
        }

        
        
    public void getMessage(String arg) {
            System.out.println(
    "Begin!");
            
            String message 
    = foo.getMessage(arg);
            System.out.println(message);
            
            System.out.println(
    "Done!");
        }

    }


    調用:

    package aop;

    public class TestStaticProxy {

        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            Foo foo 
    = new StaticProxy(new FooImpl());
            foo.getMessage(
    "Wing");
        }


    }


    結果:

    Begin!
    hi Wing
    Done
    !

    你可以看到,StaticProxy只是在Foo的某實現類基礎上包了一層,當然我們這里加的兩個輸出語句無足輕重,但如果我們把這兩個輸出語句替換成事務處理,意義就大不一樣了。

    可見,通過靜態Proxy可以實現我們的需求,但如果我們有十幾、二十個這樣的接口實現類,需要類似的處理,我們怎么辦?難道每個實現類都對應一個Proxy嗎?

    這時,我們就需要動態Proxy:

    package aop;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;

    public class AOPHandler implements InvocationHandler {
        
        
    private Object orginal;
        
        
    public Object bind(Object obj) {
            orginal 
    = obj;
            
    return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }


        
    public Object invoke(Object proxy, Method method, Object[] args)
                
    throws Throwable {
            System.out.println(
    "Begin!");
            
            Object result 
    = method.invoke(orginal, args);
            System.out.println(result);
            
            System.out.println(
    "Done!");
            
            
    return result;
        }


    }



    第一次看到上面的代碼肯定不知所以,稍后解釋,我們先看如何調用:

    package aop;

    public class TestAOP {

        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            AOPHandler handler 
    = new AOPHandler();
            Object proxy 
    = handler.bind(new FooImpl());
            
            String message 
    = ((Foo) proxy).getMessage("Wing");
            
            System.out.println(message);
        }


    }



    結果:

    Begin!
    hi Wing
    Done
    !
    hi Wing

    下面來解釋一下AOPHandler這個類:

    首先,bind()方法是用來創建動態Proxy實例。動態Proxy也是Proxy,和靜態Proxy一樣,功能上都是為了在調用某接口實現類的方法之余,添加一些額外的操作(比如事務處理),他們(動態和靜態Proxy)都是一種特殊的接口實現類。因此,我們在調用的時候可以用
    String message = ((Foo) proxy).getMessage("Wing");
    把proxy實例直接cast為Foo類型,并調用foo接口上的方法。

    不同的是,靜態Proxy,正如前面看到的,是直接實現了接口,并在接口的方法中直接調用該接口某實現類對應的方法。而動態Proxy,是利用Java.lang.reflect.Proxy類提供的這樣一種機制:當構建Proxy時,我們需要提供接口,以及一個關聯的調用處理程序對象(通常實現了InvocationHandler接口),當我們在Proxy上調用接口上的方法(任意方法)時,將觸發調用InvocationHandler接口定義的invoke()方法,由invoke方法完成相應的操作。

    上面的AOPHandler類,是將動態Proxy的構建與InvocationHandler接口的實現結合在了一起。

    通過AOPHandler,我們可以在運行時期動態的決定用哪個接口實現類來創建Proxy,而不需事先為每個實現類定義對應的Proxy,靈活性和復用性大大增強。

    進一步的,我們可以利用java反射機制,通過類名來得到接口實現類的實例,進而得到該實例的動態Proxy。這樣我們就可以在配置文件里動態指定需要用到的接口實現類,就像Spring中所做的一樣。
    posted on 2008-07-09 15:08 This is Wing 閱讀(419) 評論(0)  編輯  收藏 所屬分類: Java基礎
     
    Copyright © This is Wing Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 久久久WWW成人免费精品| 黄页网站在线视频免费| 人妻丰满熟妇无码区免费| 插鸡网站在线播放免费观看| 亚洲高清偷拍一区二区三区| 免费国产黄网站在线看| 亚洲综合激情另类专区| 在线观看人成视频免费无遮挡| 亚洲av永久无码制服河南实里| 亚洲国产欧美国产综合一区| 永久免费不卡在线观看黄网站| 在线观看人成网站深夜免费| 亚洲日本VA午夜在线影院| 久久国产免费一区二区三区 | 精品福利一区二区三区免费视频| 在线永久免费观看黄网站| 久久亚洲AV成人无码国产电影| 色欲国产麻豆一精品一AV一免费 | 成年女人男人免费视频播放| 亚洲AV日韩AV无码污污网站| 亚洲黄片毛片在线观看| 中文字幕在线免费看线人| 亚洲高清美女一区二区三区| 毛片视频免费观看| 国产福利电影一区二区三区,免费久久久久久久精 | 毛片免费观看网站| 性生大片视频免费观看一级 | 亚洲国产成人91精品| 国产成人免费a在线视频app| 久久久久久国产a免费观看不卡| 亚洲美女视频一区二区三区| 日本免费高清一本视频| 中文字幕免费在线看线人动作大片| 日本久久久久亚洲中字幕| 韩国18福利视频免费观看| 爽爽爽爽爽爽爽成人免费观看| 亚洲精品无码久久久久久久| 免费人成年激情视频在线观看| 久久午夜无码免费| 亚洲1区2区3区精华液| 亚洲AV乱码一区二区三区林ゆな|