最愛(ài)Java

          書山有路勤為徑,學(xué)海無(wú)涯苦作舟

          《AspectJ Cookbook》讀書筆記四: 捕獲方法上的連接點(diǎn)

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


          }

              
              這樣的一個(gè)方面可能執(zhí)行下來(lái)的結(jié)果是這樣的:

          ------------------- 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)

           

                  這里有一個(gè)報(bào)告需要提醒一下。我們先運(yùn)行如下代碼:

          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)方法。按照J(rèn)ava正常的執(zhí)行方法,運(yùn)行Test.java是不會(huì)牽涉到任何方面的,但事實(shí)相反,callPointCut()通知還是會(huì)被執(zhí)行。這就是AspectJ設(shè)計(jì)的比較妖怪的地方。對(duì)此,http://www.eecs.ucf.edu/~leavens/FOAL/papers-2004/barzilay-etal.pdf 有詳細(xì)的描述。有興趣的朋友可以研究一把。
          /Files/zhengzhili/Call_and_Execution_Semantics_in_AspectJ.pdf
          二. 捕獲方法調(diào)用上傳遞的參數(shù)值
              
          可以使用call(Signature)和args([TypePatterns | Identifiers])切入點(diǎn)來(lái)捕獲對(duì)方法的調(diào)用,然后把需要的標(biāo)識(shí)符綁定到方法的參數(shù)值上。

          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(
          "------------------------------------------");
              }
              
          }

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

          三. 捕獲方法調(diào)用的目標(biāo)
                  
          使用call(Signature)和targer([Type | Identifier])切入點(diǎn)來(lái)捕獲方法的調(diào)用,然后把單一標(biāo)識(shí)符綁定到正在調(diào)用方法的對(duì)象上。

          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(
          "------------------------------------------"
          );
              }
              
          }


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

          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)切入點(diǎn)相比,沒(méi)什么新的內(nèi)容。但請(qǐng)注意是什么地方調(diào)用通知,以及它的環(huán)境是什么。即請(qǐng)?zhí)貏e關(guān)注thisJoinPoint.getStaticPart().getSourceLocation()的返回值。
                  
          五. 在執(zhí)行方法時(shí)捕獲this引用的值 
                 在執(zhí)行期間捕獲方法時(shí),想通過(guò)顯示Java的this引用所指向的對(duì)象,使之可以被通知使用,可以使用execute(Signature)和this(Type | Identifier)切入點(diǎn)來(lái)捕獲方法的執(zhí)行,并把單一標(biāo)識(shí)符綁定到方式執(zhí)行期間this引用所指向的對(duì)象。

          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 閱讀(1520) 評(píng)論(2)  編輯  收藏 所屬分類: 《AspectJ Cookbook》讀書筆記

          評(píng)論

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

          怎么沒(méi)三?  回復(fù)  更多評(píng)論   

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

          學(xué)習(xí)了  回復(fù)  更多評(píng)論   

          公告


          導(dǎo)航

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

          統(tǒng)計(jì)

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 万载县| 沛县| 云梦县| 赤城县| 山丹县| 广昌县| 郧西县| 石门县| 和硕县| 北京市| 德清县| 体育| 丰顺县| 安乡县| 交口县| 洛川县| 玉山县| 扶余县| 万宁市| 新沂市| 琼海市| 太谷县| 德令哈市| 中牟县| 乐都县| 松溪县| 凤庆县| 文成县| 新乡市| 黎平县| 武威市| 吉安县| 资兴市| 应城市| 屯昌县| 宜阳县| 瑞安市| 江城| 西城区| 柞水县| 梁平县|