豆沙包

          …… …… 所學 所寫 所想 所做 所悟…… ……

          應用Java Dynamic Proxy 實現類方法的攔截(AOP)

          Java Dynamic Proxy 可以對類的指定方法實現攔截,但要求此類要實現某個Interface,攔截的方法出自此Interfacle?;诖?,我們可以實現簡單的AOP,要完成方法的攔截,只需要一個InvocationHandler,這個InvocationHandler即是攔截邏輯所在,實現了對目標object指定方法的篩選及調用。

          比如我們現有一對Interface/Implemention:Speakable/Translater。
          Speakable接口指明了可以sayEnglish(),sayChinese()。我們目前的translater實現了這兩個方法。現在我們在此基礎上,增加對translater的方法的logging功能。

          在以前,我們可以:

          1.直接改寫原代碼,增加logging功能。(ugly)
          2.增加一個LoggingTranlater實現Speakable,采用delegation(Design Pattern),對方法進行增強。對此類proxy可以參考jive,其中遍布proxy 。缺點就是每一個要增加的類都要實現一個代理類,可以想象,代碼量急劇膨脹。

          現在讓我們來看看Java Dynamic Proxy是如何達到這一點的,聲明我給出的代理是示例性的,比較簡陋,主要是給出一個實現方法,加以改進,即可形成一個比較通用的工具。

          先來看看我們的Interface/Implemention對:

          package reflection.example;

          public interface Speakable {
              
          void sayEnglish();

              
          void sayChinese();
          }


          package reflection.example;

          public class Translater implements Speakable {

              
          public void sayEnglish() {
                  System.
          out.println("Hello,i am robbie");

              }


              
          public void sayChinese() {
                  System.
          out.println("你好,我是餃子");

              }


          }


          現在我們要進行logging功能了,記住,我們只需提供一個InvocationHandler:

          package reflection.example;

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

          public class LoggingInvoktionHandler implements InvocationHandler {
              
          private Object target = null;

              
          public LoggingInvoktionHandler(Object target) {
                  
          this.target = target;
              }


              
          public Object invoke(Object proxy, Method method, Object[] args)
                      throws Throwable 
          {
                  logging(method);
                  
          return method.invoke(target, args);
              }


              
          private void logging(Method method) {
                  
          if ("sayChinese".equals(method.getName())) {
                      System.
          out.println("翻譯開始");
                  }


                  
          if ("sayEnglish".equals(method.getName())) {
                      System.
          out.println("Tranlation beginning");
                  }

              }


          }


          這個LoggingInvocationHandler實現了InvocationHandler接中。方法的代理調用在invoke(……)中,可以如我添加logging()功能一樣,加入其它的任何想要的功能,然后再進行 real target的方法調用。

          如果將logging(Method method)中的邏輯抽出來,放到外部文件(XML)中進行配置讀取。再對方法名采用正則表達式。是不是更為通用了呢?

          下面是客戶端調用:

          package reflection.example;

          import java.lang.reflect.Proxy;

          public class Main {

              
          /**
               * @param args
               
          */

              
          public static void main(String[] args) {
                  Speakable speaker 
          = new Translater();

                  Speakable loggingSpeaker 
          = (Speakable) Proxy.newProxyInstance(
                          speaker.getClass().getClassLoader(),
                          
          new Class[] { Speakable.class },
                          
          new LoggingInvoktionHandler(speaker));

                  loggingSpeaker.sayChinese();
                  loggingSpeaker.sayEnglish();
              }

          }



          是不是非常簡單呢?:)

          如果到此為止,還是看不出Dynamic在哪兒的,想想我這兒給出的示例與spring的AOP的不同,呵呵,區別在于我這兒給出的Main亦是spring AOP的一部分,在spring里, 對某個Interface的target的代理,采用了Reflection,以達到普遍適用的,不用象我這樣直接顯式地給出類名而已。若我把Main做成一個Helper類,同時,把配置接口及他的實現類都放到外部XML中配置,是不是就有點象一個超級簡化的spring AOP了?

          當然spring不是完全用Java Dynamic Proxy的,因為Java Dynamic Proxy的前提——針對接口編程!,針對普通的類的AOP,Spring采用了字節碼增強來實現。


          posted on 2005-03-04 10:37 carob 閱讀(2603) 評論(0)  編輯  收藏 所屬分類: Reflection

          主站蜘蛛池模板: 广饶县| 广宗县| 永丰县| 宣汉县| 淅川县| 彰化县| 湖州市| 始兴县| 霸州市| 夏邑县| 临泽县| 宁武县| 兰溪市| 当涂县| 杭州市| 富裕县| 威海市| 新蔡县| 华蓥市| 阳谷县| 宜昌市| 山阴县| 灵丘县| 镇雄县| 宁津县| 手机| 石门县| 图们市| 子长县| 泗洪县| 茂名市| 叶城县| 铁岭县| 新郑市| 凌海市| 亳州市| 丘北县| 庄浪县| 于田县| 云林县| 湟源县|