最愛Java

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

          《AspectJ Cookbook》讀書筆記十二: 捕獲基于布爾或復合表達式的連接點

          一.捕獲何時連接點上的運行時條件評估為true
              使用if(Expression)語句來評估包含要比較的運行時變量的布爾表達式。if(Expression)語句的語法如下:
              pointcut <pointcut name>(<any values to be picked up>) : if(<Boolean expression>);

              if(Expression)語句有兩個關鍵特征:
                  1.if(Expression)切入點評估在運行時提供的變量,得到關于連接點是否應該觸發相應通知的true或false結果。
                  2.Expression可以由多個邏輯元素組成,包括展示的連接點環境,靜態變以及其他切入點聲明。


          package com.aspectj;

          public aspect IfRecipe {
               
          // Define some variables for comparison
               private static final long realisticSalary=300001;

               
          /**
                * Specifies calling advice if this is referencing an object of class MyClass
                * and the object has a realistic salary:
                
          */

               pointcut ifJoinPointThishasRealisticSalaryPointcut():
          if(
                       (thisJoinPoint.getThis() 
          instanceof MyClass)
                       
          && ((MyClass) thisJoinPoint.getThis()).getSalary() < realisticSalary
                       
          && ((MyClass) thisJoinPoint.getThis()).getSalary() > 0)
                   
          && !withincode(* MyClass.get*())
                   
          && !execution(* MyClass.get*());
               
               
          //Advice declaration
               
          //This advice will be executed before the pointcut that picks it
                  after() : ifJoinPointThishasRealisticSalaryPointcut() && !within(IfRecipe+{
                      System.out.println(
          "---------- Aspect Advice Logic ----------");
                      System.out.println(
          "In the advice picked by ifJoinPointThishasRealisticSalaryPointcut()");
                      System.out.println(
          "Join Point Kind" + thisJoinPoint.getKind());
                      System.out.println(
          "Executing object: " + thisJoinPoint.getThis());
                      System.out.println(
          "MyClass instance: " + ((MyClass) thisJoinPoint.getThis()).getName() + ":" + ((MyClass) thisJoinPoint.getThis()).getSalary());
                      System.out.println(
          "Signature: " + thisJoinPoint.getStaticPart().getSignature());
                      System.out.println(
          "Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
                      System.out.println(
          "-----------------------------------------");        
                  }
               
          }



              if(Expression)語句允許定義是否應該把一份通知應用于特定連接點的條件邏輯。這個條件邏輯在運行時執行,并且在到達連接點那一刻必須工作在有效的類型上。
              例子中ifJoinPointThisHasRealisticSalaryPointcut()切入點中包含的條件邏輯指定在發生以下事件時,應該觸發相應的after通知:
              1.執行對象是MyClass類型
              2.對象的salary屬性小于realisticSalary常量
              3.對象的salary屬性小于0
              4.當前連接點不在getSalary()方法內。通過使用通配符,連接點絕對不能出現在開始到達的MyClass類的任何方法中。
              
              可以使用AND(&&)運算符來邏輯地結合每個條件。前3個條件可以相當容易地理解成切入點布爾邏輯的一部分,但是最后一個條件更有趣一點。必須包含!withincode(* MyClass.get*())條件,以防止從通知內調用getSalary(),這反過來又會觸發對通知的遞歸調用,并導致一個死循環。

          二.使用邏輯AND(&&)結合切入點
              使用&&運算符。&& operator運算符的語法如下:
              pointcut <pointcut name>(<any values to be picked up>) : <pointcut declaation> && <pointcut declaration>


          package com.aspectj;

          public aspect LogicalAndRecipe {
              
          /**
               * Specifies calling advice whenever a method 
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name:Any Method
               * Method Return Type:Any Return Type
               * Method Parameters:Any Parameters
               
          */

              pointcut callAnyMethodOnMyClass():call(
          * MyClass.* (..));
              
              
          /**
               * Specifies calling advice whenever a method 
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name:bar
               * Method Return Type:void
               * Method Parameters:None
               
          */

              pointcut callBarPointcut() : call(
          void MyClass.bar());
              
              
          /**
               * Specifies calling advice whenever a join points is 
               * encountered that would be picked by both pointcuts
               * specified:
               * 
               * Pointcut Name: callAyMethodOnMyClass
               * Pointcut Name:callBarPointcut
               * Method Return Type:void
               * Method Parameters:None
               
          */

              pointcut callIntersectionAnyAndBar():callAnyMethodOnMyClass() 
          && callBarPointcut();
              
              
          //Advice declaration
              before():callAnyMethodOnMyClass()&&!within(LogicalAndRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callAnyMethodOnMyClass()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          //Advice declaration
              before():callBarPointcut()&&!within(LogicalAndRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callBarPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          //Advice declaration
              before():callIntersectionAnyAndBar()&&!within(LogicalAndRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callIntersectionAnyAndBar()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }
              
          }


              在AspectJ環境中,當用&&運算符吧兩個或多個簡單的切入點結合進一步復合切入點時,被兩個獨立的切入點選擇的連接點將觸發復合切入點的關聯通知。更簡單地說,如果任一個簡單切入點選擇了任何一個連接點,那么整個復合切入點就不會選擇這個連接點。
          使用&&運算符結合切入點的次序還會影響復合切入點的解釋方式。&&運算符的運行時分析是從左到右執行的。這意味著在檢查候選連接點時,指示它不包含連接點的第一個切入點就是停止比較的地方。這對于Java中的&&運算符是成立的,并且當復合中的比較之一必須通過前一個條件加以保護時特別有用。

          三. 使用邏輯OR(||)結合切入點
              使用||運算符。|| operator運算符的語法如下:
              pointcut <pointcut name>(<any values to be picked up>) : <pointcut declaation> || <pointcut declaration>

          package com.aspectj;

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

              pointcut callFooIntStringPointcut():call(
          void MyClass.foo(int,String));
              
              
          /**
               * Specifies calling advice whenever a method 
               * matching the following rules gets called:
               * 
               * Class Name: MyClass
               * Method Name:bar
               * Method Return Type:void
               * Method Parameters:None
               
          */

              pointcut callBarPointcut() : call(
          void MyClass.bar());
              
              
          /**
               * Specifies calling advice whenever a join points is 
               * encountered that would be picked by both pointcuts
               * specified:
               * 
               * Pointcut Name: callFooIntStringPointcut
               * Pointcut Name:callBarPointcut
               * Method Return Type:void
               * Method Parameters:None
               
          */

              pointcut callIntersectionFooOrBar():callFooIntStringPointcut() 
          || callBarPointcut();
              
              
          //Advice declaration
              before():callFooIntStringPointcut()&&!within(LogicalOrRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callFooIntStringPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          //Advice declaration
              before():callBarPointcut()&&!within(LogicalOrRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callBarPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          //Advice declaration
              before():callIntersectionFooOrBar()&&!within(LogicalOrRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callIntersectionFooOrBar()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }
              
          }



              在AspectJ語言中,如果連接點在使用邏輯OR結合進入復合切入點的任何成分切入點上啟動通知,連接點就會觸發那個通知。
              AspectJ中的||運算符還顯示了短路行為,這個&&運算符相似且相反。

          四.捕獲所有未通過切入點聲明指定的連接點
              使用一元!運算符,指定忽略那些通常由特定切入點捕獲的連接點。!運算符的語法如下:
              pointcut <pointcut name>(<any values to be picked up>): !<pointcut declaation>


          package com.aspectj;

          public aspect LogicalNotRecipe {
              
          /**
               * Specifies calling advice whenever a method 
               * matching NOT match the following rules:
               * 
               * Class Name: MyClass
               * Method Name:foo
               * Method Return Type:void
               * Method Parameters:int and a String
               
          */

              pointcut notCallPointcutFooIntString() : 
          !call(void MyClass.foo(int,String));
              
              
          //Advice declaration
              before():notCallPointcutFooIntString()&&!within(LogicalNotRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by callFooIntStringPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

          }


          五.聲明匿名切入點
              匿名切入點是切入點聲明的構件。在所有基于切入點的章節中都會用它,但是我們在這里更細致地關注匿名切入點。

          package com.aspectj;

          public aspect AnonymousPointcutRecipe {
              
          /**
               * A pointcut declaration that is built up from one
               * anonymous pointcut:
               * 
               * Anonymous Pointcuts:call(void MyClass.foo(int,String))
               
          */

              pointcut singleAnonymousPointcut() : call(
          void MyClass.foo(int,String));
              
              
          /**
               * A pointcut declaration that is built up from two
               * anonymous pointcut:
               * 
               * Anonymous Pointcuts:call(void MyClass.foo(int,String))
               *                         call(void MyClass.foo(int,String))
               *                          !within(AnonymousPointcutRecipe+)
               
          */

              pointcut multipleAnonymousPointcut() : (
                      call(
          void MyClass.bar())
                      
          || call(void MyClass.foo(int,String))
                      
          && !within(AnonymousPointcutRecipe+));
              
              
          /**
               * A pointcut declaration attached to the advice it will invoke,
               * built up from anonymous pointcut:
               * 
               * Anonymous Pointcuts:within(LogicalOrRecipe+)
               
          */

              
          //Advice declaration
              before():singleAnonymousPointcut()&&!within(LogicalNotRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by singleanonymousPointcut and !within(AnonymousPointcutRecipe+)");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          /**
               * A pointcut declaration attached to the advice it will invoke,
               * built up from anonymous pointcut:
               * 
               * Anonymous Pointcuts:None
               
          */

              
          //Advice declaration
              before():multipleAnonymousPointcut() {
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by multipleAnonymousPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }
              
          }


              匿名切入點用于聲明切入點,而不是檢查特定的切入點類型。可以在命名切入點聲明內匿名地聲明切入點,或者通過把切入點直接附加到它們將調用的通知上來進行聲明。

          六.重用切入點
              聲明一個切入點,可以在需要重用它的地方通過名稱來引用它。

           

          package com.aspectj;

          public aspect PointcutReuseRecipe {
              
          /**
               * A pointcut declaration that is to be used and reused:
               * Anonymous Pointcuts: call(void MyClass.foo(int,String))
               
          */

              pointcut foundationNamedPointcut():call(
          void MyClass.foo(int,String));
              
              
          /**
               * A pointcut declaration that is built up from two
               * pointcuts:
               * 
               * Anonymous Pointcuts:!within(AnonymousPointcutRecipe+)
               * Named Pointcuts:foundationNamedPointcut()
               
          */

              pointcut reuseNamedPointcut():foundationNamedPointcut()
          &&!within(PointcutReuseRecipe+);
              
              
          /**
               * A pointcut declaration attached to the advice it will invoke,
               * built up from simple named and anonymous pointcuts:
               * Anonymous Pointcut:!within(LogicOrRecipe+)
               * Named Pointcuts:foundationNamedPointcut();
               
          */

              before():foundationNamedPointcut()
          &&!within(PointcutReuseRecipe+{
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by foundationNamedPointcut and !within(PointcutReuseRecipe+)");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }

              
              
          /**
               * A pointcut declaration attached to the advice it will invoke,
               * built up from complex pointcut built reusing other pointcut
               * declarations:
               * 
               * Named Pointcuts:reuseNamedPointcut();
               
          */

              before():reuseNamedPointcut() 
          {
                  System.out.println(
          "---------- Aspect Advice Logic ----------");
                  System.out.println(
          "In the advice picked by reuseNamedPointcut()");
                  System.out.println(
          "Signature: " + thisJoinPoint.getSignature());
                  System.out.println(
          "Source Line: " + thisJoinPoint.getSourceLocation());
                  System.out.println(
          "-----------------------------------------");        
              }
              
              
              
          }

           

          posted on 2008-08-25 20:40 Brian 閱讀(418) 評論(0)  編輯  收藏 所屬分類: 《AspectJ Cookbook》讀書筆記

          公告


          導航

          <2008年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統計

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 贵港市| 万源市| 宁城县| 乌海市| 伊川县| 清镇市| 西贡区| 宁蒗| 哈密市| 碌曲县| 汨罗市| 佳木斯市| 共和县| 崇仁县| 彭泽县| 顺平县| 安宁市| 沁水县| 旬阳县| 富宁县| 当阳市| 济南市| 牡丹江市| 扎赉特旗| 丹寨县| 新民市| 井研县| 德惠市| 泌阳县| 宜宾县| 孟村| 余江县| 大埔县| 文昌市| 革吉县| 清远市| 桐柏县| 明溪县| 界首市| 黎城县| 册亨县|