最愛Java

          書山有路勤為徑,學海無涯苦作舟

          《AspectJ Cookbook》讀書筆記四: 捕獲方法上的連接點

          一. 捕獲方法調用
                  
          使用call(Signature)切入點。其語法:
                   pointcut <pointcut name>(<any values to be picked up>) : 
                      call (<optional modifier> <return type> <class>.<method>(<paramater type>));
                   1. 在方法調用上觸發通知,其環境是調用類。
                   2. Signature可以包含通配符,用于選擇不同類和方法上的一系列連接點。
          具有通配符的簽名 描述
          * void MyClass.foo(int , float) 無論修飾符是什么,都會捕獲方法上的連接點。也可以忽略修飾符的可見性來做到這一點。
          void MyClass.foo(int , float)
          * * MyClass.foo(int , float) 無論修飾符或返回類型是什么,都會捕獲方法上的連接點。
          * MyClass.foo(int , float)
          * * *.foo(int , float) 無論修飾符,返回類型或類是什么,都會捕獲方法上的連接點。
          * *.foo(int , float)
          * * *.*(int , float) 無論修飾符,返回類型,類或者方法是什么,都會捕獲方法上的連接點。
          * * *.*(* , float) 無論修飾符,返回類型,類,或者其中的參數包含任何內容并且后接一個浮點數的方法是什么,都會捕獲方法上的連接點。
          * * *.*(* , ..) 無論修飾符,返回類型,類,或者其中的參數包含至少一個單值并且后接任意數量的方法是什么,都會捕獲方法上的連接點。
          * * *.*(..) 無論修飾符,返回類型,類,或者其中有任意數量參數的方法是什么,都會捕獲方法上的連接點。
          * *(..)
          * mypackage..*.*(..) 捕獲mypackage包和子包內的任何方法上的連接點。
          * MyClass+.*(..) 捕獲MyClass和任何子類中任何方法上的連接點。
              
                  我們來看一個最簡單的例子:
          package com.aspectj;

          public aspect CallRecipe {
              
          /*
               * Specifies calling advice whenever a mehtod
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name: foo
               * Method Return Type: void
               * Method Parameters: an int followed by a String
               
          */

              pointcut callPointCut() : call(
          void MyClass.foo(int , String));
              
              
          //Advice declaration
              before() : callPointCut() {
                  System.out.println(
          "------------------- Aspect Advice Logic -------------------");
                  System.out.println(
          "In the advice attached to the call point cut");
                  System.out.println(
          "Actually executing before the point cut call");
                  System.out.println(
          "But that's a recipe for Chapter 6!");
                  System.out.println(
          "signature: " + thisJoinPoint.getStaticPart().getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
                  System.out.println(
          "------------------------------------------");
              }


          }

              
              這樣的一個方面可能執行下來的結果是這樣的:

          ------------------- Aspect Advice Logic -------------------
          In the advice attached to the call point cut
          Actually executing before the point cut call
          But that's a recipe for Chapter 6!
          signature: void com.aspectj.MyClass.foo(int, String)
          Source Line: MyClass.java:10
          -----------------------------------------------------------

          foo(int , String)

           

                  這里有一個報告需要提醒一下。我們先運行如下代碼:

          package com.aspectj;

          public class Test extends MyClass{
              
          public void foo(int age , String name) {
                  System.out.println(
          "foo(int , String)");
              }

              
              
          public static void main(String[] args) {
                  Test c 
          = new Test();
                  c.foo(
          3 , "name");
              }


          }

                  Test.java是MyClass.java的子類,并重寫了foo(int , String)方法。按照Java正常的執行方法,運行Test.java是不會牽涉到任何方面的,但事實相反,callPointCut()通知還是會被執行。這就是AspectJ設計的比較妖怪的地方。對此,http://www.eecs.ucf.edu/~leavens/FOAL/papers-2004/barzilay-etal.pdf 有詳細的描述。有興趣的朋友可以研究一把。
          /Files/zhengzhili/Call_and_Execution_Semantics_in_AspectJ.pdf
          二. 捕獲方法調用上傳遞的參數值
              
          可以使用call(Signature)和args([TypePatterns | Identifiers])切入點來捕獲對方法的調用,然后把需要的標識符綁定到方法的參數值上。

          package com.aspectj;

          public aspect CaptureCallPamaterRrecipe {
              
          /*
               * Specifies calling advice whenever a mehtod
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name: foo
               * Method Return Type: void
               * Method Parameters: an int followed by a String
               
          */

              pointcut captureCallPamaters(
          int value , String name) : call(void MyClass.foo(int , String)) && args(value , name);
              
              
              
          //Advice declaration
              before(int value , String name) : captureCallPamaters(value , name) {
                  System.out.println(
          "------------------- Aspect Advice Logic -------------------");
                  System.out.println(
          "In the advice attached to the call point cut");
                  System.out.println(
          "Captured int parameter on method: " + value);
                  System.out.println(
          "Captured String parameter on method: " + name);
                  System.out.println(
          "------------------------------------------");
              }
              
          }

                  上例中個人理解為兩次綁定過程。第一次captureCallPamaters通過args([Types | Identifiers])將foo方法的參數綁定到自己的參數上;第二次再把自己的參數綁定到before()上。也因此,1. pointcut captureCallPamaters(int value , String name) : call(void MyClass.foo(int , String)) && args(value , name); 中參數名必須一一對應;2.before(int value , String name) : captureCallPamaters(value , name) 中參數名也必須一一對應。而1和2之間的參數名則不需要一一對應。

          三. 捕獲方法調用的目標
                  
          使用call(Signature)和targer([Type | Identifier])切入點來捕獲方法的調用,然后把單一標識符綁定到正在調用方法的對象上。

          package com.aspectj;


          public aspect CaptureCallTargetRecipe 
          {
              
          /*
               * Specifies calling advice whenever a method
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name: foo
               * Method Return Type: void
               * Method Parameters: an int followed by a String
               
          */

              pointcut captureCallTarget(MyClass myObject) : call(
          void MyClass.foo(int , String)) && target(myObject);
              
              
              
          //Advice declaration

              before(MyClass myObject) : captureCallTarget(myObject) {
                  System.out.println(
          "------------------- Aspect Advice Logic -------------------"
          );
                  System.out.println(
          "In the advice attached to the call point cut"
          );
                  System.out.println(
          "Captured target object for the method call: " +
           myObject);
                  System.out.println(
          "------------------------------------------"
          );
              }
              
          }


          四. 當執行一個方法時捕獲它
                  
          使用execution(Signature)切入點。其語法如下:
                  pointcut <pointcut name>(<any values to be picked up>) :
                      execution(<optional modifier> <return type> <class>.<method>(<paramater types>));
                  execution(Signature)切入點具有兩個關鍵特征:
                  1。觸發連接點的環境在目標類方法中。
                  2。Signature可以包含通配符,以選擇不同類和方法上的一系列連接點。

          package com.aspectj;

          public aspect ExecutionRecipe {
              
          /*
               * Specifies calling advice whenever a method
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name: foo
               * Method Return Type: void
               * Method Parameters: an int followed by a String
               
          */

              pointcut executionPointcut() : execution(
          void MyClass.foo(int , String));
              
              
              
          //Advice declaration
              before() : executionPointcut() && !within(ExecutionRecipe +{
                  System.out.println(
          "------------------- Aspect Advice Logic -------------------");
                  System.out.println(
          "In the advice picked by ExecutionRecipe");
                  System.out.println(
          "signature: " + thisJoinPoint.getStaticPart().getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
                  System.out.println(
          "------------------------------------------");
              }
              
          }

                  上述代碼和第一部分所使用的call(Signature)切入點相比,沒什么新的內容。但請注意是什么地方調用通知,以及它的環境是什么。即請特別關注thisJoinPoint.getStaticPart().getSourceLocation()的返回值。
                  
          五. 在執行方法時捕獲this引用的值 
                 在執行期間捕獲方法時,想通過顯示Java的this引用所指向的對象,使之可以被通知使用,可以使用execute(Signature)和this(Type | Identifier)切入點來捕獲方法的執行,并把單一標識符綁定到方式執行期間this引用所指向的對象。

          package com.aspectj;

          public aspect CaptureThisReferenceRecipe {
              
          /*
               * Specifies calling advice whenever a mehtod
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name: foo
               * Method Return Type: void
               * Method Parameters: an int followed by a String
               
          */

              pointcut captureThisDuringExecution(MyClass myObject) :
                  execution(
          void MyClass.foo(int , String)) && this (myObject);
              
              
          //Advice declaration
              before(MyClass myObject) : captureThisDuringExecution(myObject) {
                  System.out.println(
          "------------------- Aspect Advice Logic -------------------");
                  System.out.println(
          "In the advice attached to the execute point cut");
                  System.out.println(
          "Captured this reference: " + myObject);
                  System.out.println(
          "------------------------------------------");        
              }

          }

          posted on 2008-07-03 22:17 Brian 閱讀(1519) 評論(2)  編輯  收藏 所屬分類: 《AspectJ Cookbook》讀書筆記

          評論

          # re: 《AspectJ Cookbook》讀書筆記四: 捕獲方法上的連接點 2008-07-03 23:05 lvq810

          怎么沒三?  回復  更多評論   

          # re: 《AspectJ Cookbook》讀書筆記四: 捕獲方法上的連接點[未登錄] 2008-07-04 00:37 呵呵

          學習了  回復  更多評論   

          公告


          導航

          <2008年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統計

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 绥阳县| 湘阴县| 西华县| 弥勒县| 溆浦县| 苏尼特右旗| 宜阳县| 永寿县| 安乡县| 镇平县| 会宁县| 闵行区| 岑溪市| 大石桥市| 额济纳旗| 西昌市| 高州市| 齐河县| 康定县| 原平市| 廊坊市| 弥渡县| 柳河县| 马边| 尚义县| 洛隆县| 龙海市| 常宁市| 寿阳县| 峡江县| 富民县| 砚山县| 彭阳县| 利津县| 通城县| 封开县| 靖江市| 东乌珠穆沁旗| 太湖县| 鄂伦春自治旗| 陵川县|