豆沙包

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

          應用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 閱讀(2598) 評論(0)  編輯  收藏 所屬分類: Reflection

          主站蜘蛛池模板: 高碑店市| 都安| 德州市| 南郑县| 德安县| 托克托县| 闵行区| 东丽区| 祁东县| 广灵县| 罗源县| 全州县| 从江县| 简阳市| 聂荣县| 奉节县| 精河县| 长白| 锦屏县| 犍为县| 章丘市| 运城市| 利辛县| 芮城县| 锦屏县| 沈丘县| 尚义县| 罗平县| 洛阳市| 博乐市| 梁平县| 宣化县| 手游| 松溪县| 申扎县| 南皮县| 上高县| 华宁县| 墨脱县| 镇宁| 宁晋县|