Spring AOP筆記

 1、概念定義spring

     通知:定義了切面的"什麼"和"什麼時候"。express

     切點:定義了切面的"何處"。用於準肯定位應該在什麼地方應用切面的通知。app

     切面:切面是通知和切點的集合。.net

     鏈接點:在應用執行過程當中可以插入切面的一個點。代理

     織入:將切面應用到目標對象來建立新的代理對象的過程。orm

2、使用切點選擇鏈接點對象

    在Spring AOP中,須要使用AspectJ的切點表達式語言來定義切點。Spring僅支持AspectJ切點指示器的子集。其中只有execution指
示器是惟一的執行匹配,其餘的指示器都是限制匹配的。get

    一、切點的編寫it

        示例1:execution(* com.springinaction.springidol.Instrument.play(...))
                咱們使用execution()指示器選擇Instrument的play()方法。方法表達式以*號隔開,標識了咱們不關心方法返回值的類型。而後,咱們制訂了全限定名和方法。方法中的(...)標識切點選擇任意的play()方法,不管方法入參是什麼。io

    示例2:execution(* com.springinaction.springidol.Instrument.play(...)) && within(com.springinaction.spriingidol.*)
                咱們使用within()指示器來限制切點僅匹配com.springinaction.springidol包。

3、在XML中聲明切面

   一、 聲明前置通知和後置通知:
    聲明一個audience Bean:
    <bean id="audience" class="com.springinaction.springidol.Audience" />

    把audience Bean聲明爲一個切面:
    <aop : config>
        <aop : aspect ref="audience">
            <aop : before pointcut="execution(* com.springinaction.springidol.Performer(...))" method="takeSeats" />
            <aop : before pointcut="execution(* com.springinaction.springidol.Performer(...))" method="turnOffCellPhones" />
            <aop : after-returning  pointcut="execution(* com.springinaction.springidol.Performer(...))" method="applaud" />
            <aop : after-throwing pointcut="execution(* com.springinaction.springidol.Performer(...))" method="demandRefund" />
        </aop : aspect>
    </aop : config>

pointcut屬性的值定義了通知應用的切點。pointcut屬性的值是使用AspectJ切點表達式語法所定義的切點。

定義一個命名切點消除冗餘的切點定義:
    
    <aop : config>
        <aop : aspect ref="audience">
            <aop : pointcut id="performance" expression="execution(* com.springinaction.springidol.Performer(...))">
            <aop : before pointcut-ref="performance" method="takeSeats" />
            <aop : before pointcut-ref="performance" method="turnOffCellPhones" />
            <aop : after-returning  pointcut-ref="performance" method="applaud" />
            <aop : after-throwing pointcut-ref="performance" method="demandRefund" />
        </aop : aspect>
    </aop : config>

 
  二、聲明環繞通知
        這是環繞通知方法:
        public void watchPerformance(ProceedingJoinPoint  joinpoint){
            try{
                System.out.println("The audience is taking their seats.");                //表演以前
                System.out.println("The audience is turning off their cellphones.");

                joinpoint.proceed();                        //執行被通知的方法

                long end = System.currentTimeMillis();                        //表演以後
                System.out.println("CLAP CLAP CLAP CLAP CLAP CLAP ");
                System.out.println("The performance took " + (end - start));
            }catch(Throwable t){
                 System.out.println("Boo! we want our money back!");               //表演失敗以後
             }
        }

        該通知方法使用了ProceedingJoinPoint做爲方法的入參,該對象能讓咱們在通知裏調用被通知的方法。
        若是咱們忘記調用proceed()方法,通知將會阻止被通知方法的調用。
        在此audience切面,watchPerformance()方法包含以前4個通知方法的全部邏輯,但全部邏輯都放在一個方法中了。

    聲明環繞通知:
    <aop : config>
        <aop : aspect ref="audience">
            <aop : pointcut id="performance2" expression="execution(* com.springinaction.springidol.Performer(...))">
            <aop : around pointcut-ref="performance" method="watchPerformance()" />
        </aop : aspect>
    </aop : config>

三、爲通知傳遞參數
 
有時候通知並不單單是對方法進行簡單的包裝,還須要檢驗傳遞給方法的參數值,這時候爲通知傳遞參數就很是有用了。

4、註解切面

    一、註解前置、後置通知:

    package  com.springinaction.springidol;

    @Aspect                                                             
    public class Audience {
        @Pointcut(                                                   //定義切點
                        "execution(* com.springincation.springidol.Performer.perform( .. ))")
    public void performance(){
    }
    
    @Before("performance()")                            //表演以前
    public void takeseats(){
        System.out.println("The audience is taking their seats.");
   
    @Before("performance()")                           //表演以前
    public void turnoffCellPhones(){
        System.out.println("The audience is turning off their cellphones.");
    
    
    @AfterReturning("performance()")            //表演以後
    public void applaud(){
        System.out.println("CLAP CLAP CLAP CLAP CLAP");

    @AfterThrowing("performance()")            //表演失敗以後
    public void demandRefund(){
        System.out.println("Boo! We want our money back!");
    }
    }

    新的Audience類使用@AspectJ註解進行了標註。該註解標註了Audience不單單是一個POJO,仍是一個切面。

    @pointCut註解用於定義一個能夠在@AspectJ切面內可重用的切點。切點的名稱來源於註解所應用的方法名稱。所以該切點名稱爲performance()。performance()方法在這裏是空的,該方法自己只是一個標識,供@pointCut註解依附。

二、註解環繞通知:

    @Around("performance()")
    public void watchPerformance(ProceedingJoinPoint joinpoint){
        try{
            System.out.println("The audience is taking their seats.");
            System.out.println("The audience is turning off their cellphones.");
            
            long start = System.currentTimeMillis();
            joinpoint.proceed();
            long end = System.currentTimeMillis();

            System.out.println("CLAP CLAP CLAP CLAP CLAP !");             System.out.println("The performance took" + (end - start) + "milliseconds");         }catch(Throwable t ){             System.out.println("Boo! We want our money back!");         }     }  

相關文章
相關標籤/搜索