<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    最愛Java

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

    《AspectJ Cookbook》讀書筆記十三: 定義通知

    一.訪問類成員 

    package com.aspectj;

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

        pointcut executionOfFooPointCut() : execution(
    void MyClass.foo(int,String));
        
        
    //Advice declaration
        after(MyClass myClass):executionOfFooPointCut() && this(myClass){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Accessing the set(float) member of the MyClass object");
            System.out.println(
    "Privileged access not  required for this method call as it is public");
            myClass.setF(
    2.0f);
            System.out.println(
    "Using the privileged aspect access to the private f member variable");
            System.out.println(
    "The current value of f is: ");
            System.out.println(myClass.f);
            System.out.println(
    "Signature: " + thisJoinPoint.getSignature());
            System.out.println(
    "Source Line: " + thisJoinPoint.getSourceLocation());
            System.out.println(
    "-----------------------------------------");        
        }

    }


            通過使用this(Identifier)切入點定義,使得MyClass類的對象可供通知使用。this(Identifier)切入點定義有效地把通知展示給被觸發連接點處的this引用指向的對象。從通知內調用setF(float)方法,并顯示對MyClass對象的公共方法的訪問。為了獲得對MyClass.f私有屬性的訪問,方面不得不對其結構執行一些額外的更改。方面嘗試通過直接訪問私有成員來破快封裝性,因此,必須把方面聲明為privileged,因為它正在提交潛在的侵入動作。
            AspectJ提供了privieged關鍵字,它用在方面需要完全不受限制地訪問類的地方,包括那些未在類的公共接口上聲明的成員變量和方法。方面的privileged狀態應該充當一個警告,在對方面或者它所應用的類執行任何更改時,必須當心這個警告,因為這些更改可能潛在地在整個應用程序中引發其他問題。

    二.訪問連接點環境
            AspectJ提供了thisJoinPoint變量,用于展示this連接點環境。如果可以靜態地訪問正在訪問的環境,那么thisJoinPointStaticPart也是有用的。

    package com.aspectj;

    public aspect ThisJoinPointRecipe {
        
    /**
         * Specifies calling advice whenever a method 
         * matching the following rules gets executed:
         * 
         * 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()&&!within(ThisJoinPointRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Exercising the static parts of AspectJ 1.1.1 thisJoinPoint");
            System.out.println(
    "Source Line: " + thisJoinPointStaticPart.getSourceLocation());
            System.out.println(
    "JoinPoint Kind: " + thisJoinPointStaticPart.getKind());
            System.out.println(
    "Simple toString: " + thisJoinPointStaticPart.toString());
            System.out.println(
    "Simple toShortString: " + thisJoinPointStaticPart.toShortString());
            System.out.println(
    "Simple toLongString: " + thisJoinPointStaticPart.toLongString());
            System.out.println(
    "Exercising the join point generic signature of AspectJ 1.1.1 thisJoinPoint");
            System.out.println(
    "Signature name:" + thisJoinPointStaticPart.getSignature().getName());
            System.out.println(
    "Signature declaring type:" + thisJoinPointStaticPart.getSignature().getDeclaringType());
            System.out.println(
    "-----------------------------------------");        
        }

        
        before():callPointCut()
    &&!within(ThisJoinPointRecipe+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Exercising the dynamic parts of AspectJ 1.1.1 thisJoinPoint");
            System.out.println(
    "Get the this reference: " + thisJoinPoint.getThis());
            System.out.println(
    "Getting the Target: " + thisJoinPoint.getTarget());
            System.out.println(
    "Join Point Arguments:");
            Object[] args 
    = thisJoinPoint.getArgs();
            
    for (int count = 0; count < args.length ; count++{
                System.out.println(args[count]);
            }

            System.out.println(
    "-----------------------------------------");        
        }

    }

            thisJoinPoint變量包含關于觸發連接點的靜態和動態環境信息。靜態環境信息包含可以在編譯和織入時決定的任何信息。動態連接點環境信息則只能在運行時填充,因為它依賴于連接點環境實際的運行時狀態。

    三.在連接點之前執行通知
            使用before()類型的通知

     

    package com.aspectj;

    public aspect BeforeAdviceRecipe {
        
    /**
         * Specifies calling advice whenever a method 
         * matching the following rules gets executed:
         * 
         * 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()&&!within(BeforeAdviceRecipe+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());        
            System.out.println(
    "-----------------------------------------");        
        }

    }


    四.在連接點周圍執行通知
            使用around()類型的通知。

    package com.aspectj;

    public aspect AroundAdviceRecipe {
        
    /**
         * 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 callFooPointCut() : call(
    int MyClass.foo());
        
        
    /**
         * Specifies calling advice whenever a method 
         * matching the following rules gets called:
         * 
         * Class Name: MyClass
         * Method Name:bar2
         * Method Return Type:int
         * Method Parameters:an int 
         
    */

        pointcut callBarPointCut(
    int value) : call(int MyClass.bar(int)) && args(value);
        
        
    /**
         * Specifies calling advice whenever a method 
         * matching the following rules gets called:
         * 
         * Class Name: MyClass
         * Method Name:baz
         * Method Return Type:int
         * Method Parameters: 
         
    */

        pointcut callBazPointCut() : call(
    int MyClass.baz());
        
        
    //Advice declaration
        
    //This advice will be executed before the pointcut that picks it
        int around() : callFooPointCut()&& !within(AroundAdviceRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Signature: " + thisJoinPoint.getSignature());
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");
            
    return proceed();
        }

        
        
    //Advice declaration
        
    //This advice will be executed before the pointcut that picks it
        int around(int value):callBarPointCut(value)&&!within(AroundAdviceRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Signature: " + thisJoinPoint.getSignature());
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");
            
    return proceed(value);        
        }

        
        
    //Advice declaration
        
    //This advice will be executed before the pointcut that picks it
        int around(int value):callBarPointCut(value)&&!within(AroundAdviceRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Signature: " + thisJoinPoint.getSignature());
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");
            
    return proceed(value);        
        }

        
        
    //Advice declaration
        
    //This advice will be executed before the pointcut that picks it
        int around() : callBazPointCut() && !within(AroundAdviceRecipe+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Signature: " + thisJoinPoint.getSignature());
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");
            
    return 200;            
        }

    }


            around()通知是一種強大的構造,它指示AspectJ應該運行通知,而不是指示連接點觸發它。這允許重寫應用程序中存在的原始邏輯。這說明了around()通知,可以依據是否從around()通知塊內發起proceed()調用,來被動或主動地應用這個通知。
            proceed()調用指示around()通知應該繼續執行原始連接點邏輯,并傳遞原來可用的任何值。
    在示例中,第一份通知沒有參數需要傳遞;第二份通知傳遞了一個與原始值完全不同的值;第三份通知則完全返回了一個不同的值。
            around()通知必須具有指定的返回值,但是如果不需要值,那么可以是void。

    五.在連接點之后無條件執行通知
            使用after()類型的通知

     

    package com.aspectj;

    public aspect AfterAdviceRecipe {
        
    /**
         * 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 callPointCut() : call(
    void MyClass.foo(int,String));
        
        
    //Advice declaration
        after():callPointCut()&&!within(AfterAdviceRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");        
        }

    }


    六.僅在從連接點正常返回之后才執行通知
            使用after() returning或after() returning(<ReturnType> <Identifier>)類型的通知

     

    package com.aspectj;

    public aspect AfterReturningAdviceRecipe {
        
    /**
         * 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 callPointCut():call(
    void MyClass.foo(int));
        
        
    //Advice declaration
        after() returning:callPointCut()&&!within(AfterReturningAdviceRecipe+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");        
        }

    }

     

    package com.aspectj;

    public aspect AfterReturningValueAdviceRecipe {
        
    /**
         * 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 callPointCut():call(
    void MyClass.foo(int));
        
        
    //Advice declaration
        after() returning(Object value):callPointCut()&&!within(AfterReturningAdviceRecipe+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "Value being returned: " + value);
            System.out.println(
    "-----------------------------------------");        
        }

    }


            使用after() returning(<ReturnType> <Identifier>)通知訪問基本類型的一個有趣作用是:必須把基本的int值裝箱進Integer類的一個實例中,以傳遞給通知。當通知期待的返回類型是Object類型時,并且如果返回值是基本類型,AspectJ將自動并且透明地把基本值裝箱進其對應的Java類中。around()形式的通知也可以使用這種自動和透明的裝箱行為,其中會期待Object類型的值,并且將從通知傳遞基本值或將基本值傳遞給通知。
    與正常的ater()相比,after() returning形式的通知提供了更精細的過濾器。

    七.僅當連接點中引發了一個異常之后才執行通知
            使用after() throwing或after() throwing(<ExceptionType> <Identifier>)類型的通知。

     

    package com.aspectj;

    public aspect AfterThrowingAdviceRecipe {
        
    /**
         * 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 callPointCut():call(
    void MyClass.foo(int));
        
        
    //Advice declaration
        after() throwing:callPointCut()&&!within(AfterThrowingAdviceRecipe+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");        
        }

    }


    八.控制通知優先級
            如果把位于不同方面中的相同類型的通知應用同一連接點,則可以使用declare precedence通知。其語法如下:
            declare precedence:TypePattern,TypePattern,...;

    package com.aspectj;

    public aspect AspectA {
        
    // Declare precedence rules
        declare precedence:AspectA,AspectB;

        
    /**
         * 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 callPointCut():call(
    void MyClass.foo(int,String));

        
    // Advice declaration
        before():callPointCut()&&!within(AspectA+){
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "In the advice of AspectA");
            System.out.println(
    "Target: " + thisJoinPoint.getTarget());
            System.out.println(
    "This: " + thisJoinPoint.getThis());
            System.out.println(
    "Aspect Instance: " + AspectA.aspectOf());
            System.out.println(
    "-----------------------------------------");
        }

    }


            在declare precedence語句中使用TypePattern來指定不同的方面,以及他們的顯式次序。可以使用通配符來指定TypePatterns,以根據需要為特定的方面集合或方面的整個包指示優先級。
    當把一個方面中的兩個相同類型的通知塊應用于同一個連接點時,declare precedence語句就沒有意義了。為了處理這種情況,AspectJ基于方面聲明內通知的類型和位置,來應用隱式的優先級次序:
    • 按在方面中聲明before()和around()通知類型的次序,來應用他們隱式優先級規則。如果把同一方面的兩個before()通知塊應用于同一個連接點,那么聲明第一個塊將具有最高的優先級,而最后一個則最低。
    • 而after()、aftr() returning和around() throwing通知類型的隱式優先級則于before()相反。

    九.通知方面

    package com.aspectj;

    public aspect AdviseAspectRecipe {
        
    /**
         * 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 callPointCut():call(
    void MyClass.foo(int,String));
        
        
    //Advice declaration
        before() : callPointCut()&&within(AdvisedAspect+{
            System.out.println(
    "---------- Aspect Advice Logic ----------");
            System.out.println(
    "In the advice attached to the call point cut");
            System.out.println(
    "Signature: " + thisJoinPoint.getStaticPart().getSignature());
            System.out.println(
    "Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
            System.out.println(
    "-----------------------------------------");        
        }

    }


    posted on 2008-08-26 13:45 Brian 閱讀(1558) 評論(1)  編輯  收藏 所屬分類: 《AspectJ Cookbook》讀書筆記

    評論

    # re: 《AspectJ Cookbook》讀書筆記十三: 定義通知 2008-08-26 18:05 隔葉黃鶯

    AspectJ 確實很靈活,我很早也看過了這本書,只是實際中寫 aj 文件的機會還沒有,學到相關的知識可運用于 Spring 2.0 的 AspectJ 方式 AOP 相關配置。  回復  更多評論   

    公告


    導航

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

    統計

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    收藏夾

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 成全视频在线观看免费高清动漫视频下载 | 好先生在线观看免费播放| 成人啪精品视频免费网站| 国产精品无码一二区免费| JLZZJLZZ亚洲乱熟无码| 久久99国产亚洲精品观看| 亚洲乱码在线视频| 色屁屁www影院免费观看视频| 国产成人高清精品免费观看| 久久免费观看国产精品| 国产人在线成免费视频| 国产黄色片在线免费观看| 亚洲综合无码精品一区二区三区| 亚洲自偷自拍另类图片二区| 亚洲a∨无码精品色午夜| 国产福利免费视频 | 国产高清免费的视频| 久久夜色精品国产亚洲av| 亚洲欧洲第一a在线观看| 亚洲中文精品久久久久久不卡| 免费很黄无遮挡的视频毛片| 最好免费观看高清在线 | 91视频免费观看| 免费看污成人午夜网站| 亚洲成A∨人片天堂网无码| 久久精品国产亚洲av高清漫画| 亚洲av无码成人精品国产| 成全高清在线观看免费| 97视频热人人精品免费| 中文字幕日韩亚洲| 亚洲国产人成在线观看| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 无人在线观看免费高清| 在线播放高清国语自产拍免费| 久久精品国产精品亚洲人人| 亚洲AV成人噜噜无码网站| 国产视频精品免费视频| 嫩草影院免费观看| 亚洲色图在线播放| 精品在线观看免费| 3344免费播放观看视频|