SpringMVC 的 切面


官網路徑:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans

一:術語介紹

通知(Advice)

指切面(定義為aspect的類)中的工作;

spring切面可以應用的五種通知:

前置通知(Before):在目標方法被調用之前調用通知功能;

后置通知(After):在目標方法完成之后調用通知,此時不會關心方法的輸出是什么;

返回通知(After-returning):在目標方法成功執行之后調用通知;

異常通知(After-throwing):在目標方法拋出異常后調用通知;

環繞通知(Around):通知報過了被通知的方法,在被通知的方法調用之前和調用之后執行自定義的行為。

連接點(Join point)

連接點是在應用執行過程中能夠插入切面的一個點。這個點可以是調用方法時,拋出異常時,甚至修改一個字段時。切面代碼可以利用這些點插入到應用的正常流程之中,並添加新的行為。(切點方法中配置的匹配的方法都是連接點)

 

切點(Pointcut)

定義通知所要織入的一個或多個連接點。

 

切面(Aspect)

是通知和切點的結合。

 

引入(Introduction)

向現有的類添加新的方法和屬性。

織入(Weaving)

織入是把切面應用到目標對象並創建新的代理對象的過程。切面在指定的連接點被織入到目標對象中。在目標對象的生命周期里有多個點可以進行織入:

編譯期:切面在目標類編譯時被織入,這種方式需要特殊的編譯器。AspectJ的織入編譯器就是以這種方式織入切面的。

類加載期:切面在目標類加載到jvm時被織入。這種方式 需要特殊的類加載器(ClassLoader),它可以在目標類被引入應用之前增強該目標類的字節碼。AspectJ5的加載時織入(load-time weaving,LTW)就支持以這種方式織入切面。

運行期:切面在應用運行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標對象動態的創建一個代理對象。Spring AOP就是以這種方式織入切面的。

下圖展示了這些概念是如何聯系在一起的。

 

 

下面了解一下具體的切點表達式。在spring的切面中,主要使用execution指示器來設置匹配的方法。下圖中的表達式能夠設置當sleep()方法執行時觸發的通知調用。
execution()指示器選擇ViewController的sleep()方法,方法表達式以“*”號開始,表明了不關心方法返回值的類型。然后,指定了全限定方法名和類名。對於方法參數列表,使用兩個點號(. .)表明切點要選擇任意的sleep()方法,不需要考慮入參。

 


使用AspectJ切點表達式來選擇ViewController的sleep方法


如果我們需要設定切點僅適用於某個包下的方法,則可以使用within()指示器來指定,不同的指示器之間使用&&(and)或||(or)連接。如下圖表達式,表示只匹配com.spring包下的ViewController的sleep()方法。

 

spring中還引入了bean()指示器,可以限制切點只匹配特定的bean,也可以使用!bean()來匹配除了特定bean以外的其他bean。如下:
execution(*  com.spring.ViewController.sleep())   and  bean ("rest")

execution(*  com.spring.ViewController.sleep())   and  !bean ("rest")

下面寫一個切面的demo。

首先,在com.spring下的ViewController類中添加一個sleep()方法如下:

@RequestMapping("/sleep")
public String sleep(){
    System.out.println("sleeping………………zzzZZZ~~~~");
    return "index";
}

 


然后,添加切面代碼。使用注解新建一個切面SleepHelper,代碼如下。

@Component
@Aspect
public class SleepHelper {

public SleepHelper(){

}

@Pointcut("execution(* com.spring.controller.ViewController.*(..))")
public void sleeppoint(){
}

@Before("sleeppoint()")
public void beforeSleep(){
 System.out.println("馬上要睡覺咯~~~");
}

@AfterReturning("sleeppoint()")
public void afterSleep(){

System.out.println("睡醒咯!");
}

}

 當然也可以這么定義

@Before("execution(* com.spring.controller.ViewController.save(..)) && args(para1,para1)")
public void test(String para1,String para1) throws Exception {
    params= obj;
}

關於參數:

com.spring.controller.ViewController.save(..)
此處為切入到具體方法:
save(..)  -- .. 表示所有參數
args(para1,para1) 此處為具體參數
public void test(String para1,String para1) --方法里面的可以拿出來在方法中使用

最后,項目是maven的項目,所以需要在pom.xml中添加切面對應的依賴jar包,並在applicationContext.xml文件中添加下圖紅框中的內容:

 


第一個紅框中內容作用:聲明spring的aop的命名空間;
第二個紅框中內容作用:啟用aspectj的自動代理;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM