一、前置/後置/返回/異常/通知
Spring在執行AOP時實際上流程以下:
- 首先執行前置通知
- 而後執行目標組件,若是過程當中出現異常,則執行異常通知
- 而後執行後置通知
- 最後判斷若是目標組件正常執行,則再執行返回通知
- before,前置通知,組件參數有JoinPoint
- after,後置通知,組件參數有JoinPoint
- after-returning,返回通知,組件參數除了JoinPoint,還有Object做爲返回值,需在配置文件中定義
- after-throwing,異常通知,組件參數除了JoinPoint,還有Throwable,會在目標程序拋出異常以後獲取,也須要在配置文件中定義
二、環繞通知
經過環繞通知,能夠實現前置通知、後置通知等等能夠實現的功能。在類型爲環繞通知的切面程序函數中,參數則再也不是JoinPoint,而是ProceddingJoinPoint,它是JoinPoint的子類,進行了擴展,提供了proceed()函數,該函數的做用是調用目標組件,並返回目標組件返回的值。
public void doAround(ProceedingJoinPoint point) {
System.out.println("目標組件運行的前置通知");
try {
Object obj = point.proceed();
System.out.println("目標組件的返回通知");
} catch (Throwable throwable) {
System.out.println("執行異常處理程序");
}
System.out.println("最終執行程序");
}
<aop:aspect ref="section">
<!-- 通知爲環繞,method爲方法,pointcut-ref做用在哪些切入點 -->
<aop:around method="doAround" pointcut-ref="targetPointCut"/>
</aop:aspect>
三、切入表達式
切入表達式用於聲明Spring容器中哪些組件的函數是目標函數,也就是切面程序要做用到哪些組件的哪些函數上。
經常使用的切入表達式分爲:
- 按類匹配
- 匹配的Java類中所有函數做爲目標函數,使用within關鍵字
- 按函數匹配
- 匹配的函數做爲目標函數,使用execution關鍵字
- 按bean的id匹配
- 匹配的bean中所有函數做爲目標函數,使用bean關鍵字
3.1 按類匹配
匹配到指定類
.Xxx
<aop:pointcut id="targetPoint" expression="within(dulk.learn.aop.Target)" />
匹配到包下的類 .*
<aop:pointcut id="targetPoint" expression="within(dulk.learn.aop.*)" />
匹配到包下及子包下的類
..*
<aop:pointcut id="targetPoint" expression="with(dulk..*)" />
3.2 按函數匹配
表達式的完整寫法(以以前的demo爲示例):
execution(String dulk.learn.aop.Target.print(String))
如上:
- 首個String - 表示返回類型
- dulk.learn.aop - 表示類的路徑
- Target - 表示類名
- print - 表示函數名
- 最後個String - 表示參數類型,用","分開
任意返回類型
execution(* dulk.learn.aop.Target.print(String))
任意返回類型下指定包下任意類
execution(* dulk.learn.aop.*.print(String))
任意返回類型下指定包下任意類任意函數
execution(* dulk.learn.aop.*.*(String))
任意返回類型下指定包或子包下任意類任意函數任意參數
execution(* dulk..*.*(..))
3.3 按bean的id匹配
表達式的關鍵字爲bean,以後括號中的內容則爲對應bean組件的id。
根據bean組件名稱匹配:
<aop:pointcut id="targetPoint" expression="bean(target)" />
根據bean組件名稱(含通配符)匹配,若有target1,target2等bean組件,則能夠統一使用target*表示:
<aop:pointcut id="targetPoint" expression="bean(target*)" />