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

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

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

    最愛Java

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

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

    二.訪問連接點環(huán)境
            AspectJ提供了thisJoinPoint變量,用于展示this連接點環(huán)境。如果可以靜態(tài)地訪問正在訪問的環(huán)境,那么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變量包含關(guān)于觸發(fā)連接點的靜態(tài)和動態(tài)環(huán)境信息。靜態(tài)環(huán)境信息包含可以在編譯和織入時決定的任何信息。動態(tài)連接點環(huán)境信息則只能在運行時填充,因為它依賴于連接點環(huán)境實際的運行時狀態(tài)。

    三.在連接點之前執(zhí)行通知
            使用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(
    "-----------------------------------------");        
        }

    }


    四.在連接點周圍執(zhí)行通知
            使用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()通知是一種強大的構(gòu)造,它指示AspectJ應(yīng)該運行通知,而不是指示連接點觸發(fā)它。這允許重寫應(yīng)用程序中存在的原始邏輯。這說明了around()通知,可以依據(jù)是否從around()通知塊內(nèi)發(fā)起proceed()調(diào)用,來被動或主動地應(yīng)用這個通知。
            proceed()調(diào)用指示around()通知應(yīng)該繼續(xù)執(zhí)行原始連接點邏輯,并傳遞原來可用的任何值。
    在示例中,第一份通知沒有參數(shù)需要傳遞;第二份通知傳遞了一個與原始值完全不同的值;第三份通知則完全返回了一個不同的值。
            around()通知必須具有指定的返回值,但是如果不需要值,那么可以是void。

    五.在連接點之后無條件執(zhí)行通知
            使用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(
    "-----------------------------------------");        
        }

    }


    六.僅在從連接點正常返回之后才執(zhí)行通知
            使用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類的一個實例中,以傳遞給通知。當(dāng)通知期待的返回類型是Object類型時,并且如果返回值是基本類型,AspectJ將自動并且透明地把基本值裝箱進其對應(yīng)的Java類中。around()形式的通知也可以使用這種自動和透明的裝箱行為,其中會期待Object類型的值,并且將從通知傳遞基本值或?qū)⒒局祩鬟f給通知。
    與正常的ater()相比,after() returning形式的通知提供了更精細的過濾器。

    七.僅當(dāng)連接點中引發(fā)了一個異常之后才執(zhí)行通知
            使用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(
    "-----------------------------------------");        
        }

    }


    八.控制通知優(yōu)先級
            如果把位于不同方面中的相同類型的通知應(yīng)用同一連接點,則可以使用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,以根據(jù)需要為特定的方面集合或方面的整個包指示優(yōu)先級。
    當(dāng)把一個方面中的兩個相同類型的通知塊應(yīng)用于同一個連接點時,declare precedence語句就沒有意義了。為了處理這種情況,AspectJ基于方面聲明內(nèi)通知的類型和位置,來應(yīng)用隱式的優(yōu)先級次序:
    • 按在方面中聲明before()和around()通知類型的次序,來應(yīng)用他們隱式優(yōu)先級規(guī)則。如果把同一方面的兩個before()通知塊應(yīng)用于同一個連接點,那么聲明第一個塊將具有最高的優(yōu)先級,而最后一個則最低。
    • 而after()、aftr() returning和around() throwing通知類型的隱式優(yōu)先級則于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 閱讀(1562) 評論(1)  編輯  收藏 所屬分類: 《AspectJ Cookbook》讀書筆記

    評論

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

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

    公告


    導(dǎo)航

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

    統(tǒng)計

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    收藏夾

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲片国产一区一级在线观看| 亚洲一区精彩视频| 情侣视频精品免费的国产| 无码人妻久久一区二区三区免费| 色综合久久精品亚洲国产| 亚洲一区二区三区在线观看蜜桃| 国产亚洲3p无码一区二区| 亚洲黄色片免费看| 亚洲色爱图小说专区| 亚洲一区视频在线播放| 国产精品免费播放| 18禁无遮挡无码网站免费| 7x7x7x免费在线观看| 黄色网站软件app在线观看免费| 狼色精品人妻在线视频免费| 亚洲一本到无码av中文字幕| 亚洲欧洲日韩综合| 亚洲美免无码中文字幕在线| 久久伊人久久亚洲综合| 久久亚洲国产精品一区二区| 狠狠亚洲狠狠欧洲2019| 亚洲av无码国产精品色在线看不卡 | 国产亚洲综合一区二区三区| 精品国产日韩久久亚洲| 亚洲人成影院午夜网站| 亚洲日本视频在线观看| 亚洲综合网美国十次| 亚洲视频免费在线播放| 中文字幕在线观看亚洲| 久久精品国产亚洲av水果派| 亚洲国产精品一区| 精品日韩亚洲AV无码| 亚洲色成人网一二三区| 亚洲精品mv在线观看| 亚洲第一区视频在线观看| 亚洲成人免费网址| 亚洲最大成人网色香蕉| 亚洲综合久久精品无码色欲 | 午夜a级成人免费毛片| 日本免费电影一区| 亚洲美女高清一区二区三区|