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