目錄
1.AOP概念理解
軟件開發中散佈於應用中多處的功能被稱爲橫切關注點,把這些橫切關注點與業務邏輯分離,正是面向切面編程所要關注的問題,AOP是一種編程的範式,類似於面向過程,面向函數編程,面向對象編程一樣。另外他解決的是特定的問題而不是所有的問題。
Spring AOP 構建在動態代理的基礎上,因此Spring 對 AOP的支持侷限於方法攔截,如果需要方法攔截之外的連接點的攔截功能,那麼我們可以利用AspectJ來補充Spring AOP的功能。
AOP相關注解
@EnableAspectJAutoProxy
@Aspect
@PointCut
@Before、@Around、@After
@AfterReturning
@AfterThrowing
AOP的初衷是什麼?第一個初衷就是消除重複的代碼。第二個初衷是將關注點分離:
使用AOP的好處:
AOP的使用場景:
橫切關注點被模塊化爲特殊的類,這個類就被稱爲切面。
通知定義了切面是什麼以及何時使用,通知包含了需要應用於多個應用對象的橫切行爲。
連接點是在應用執行過程中能夠插入切面的一個點。,是程序執行過程中能夠應用通知的所有點。
切點的定義會匹配通知所要織人的一個或多個連接點。切點定義了通知被應用的具體位置。
織入是把切面應用到目標對象並創建新的代理對象的過程。
最關鍵的概念就是切點定義了哪些連接點會得到通知。創建切點來定義切面所織入的連接點是AOP框架的基本功能。
2.切點表達式的構成
切面表達式,切點表達式中主要包含三個部分:通配符,運算符,指示器。
重點是execution()
匹配包:
匹配對象:第三個是根據bean的id來匹配的
參數匹配:
註解匹配:
只想攔截拋出異常的方法
3.Spring AOP實例:
先要找到應用中的連接點,即需要通知的點。
編寫切面和切點表達式:
@Aspect
public class Audience {
//定義命名的切點
@Pointcut("execution(* *com.wx.springinaction.service.Performance.perform(..))")
public void performance() {
}
@Before("performance()")
public void silenceCellPhone() {
System.out.println("看錶演之前,觀衆將收集調成靜音");
}
@Before("performance()")
public void takeSeats() {
System.out.println("觀衆入席坐好");
}
// @After 和 @AfterReturning區別:@After=@AfterReturning+@AfterThrowing
@AfterReturning("performance()")
public void applause() {
System.out.println("演出結束觀衆鼓掌");
}
@AfterThrowing("performance()")
public void demandRefund() {
System.out.println("演出失敗,觀衆要求退款!!!");
}
}
注入切面的bean
@Configuration
@EnableAspectJAutoProxy //啓動AspectJ自動代理
@ComponentScan("com.wx.springinaction.service")
public class PerformanceConfig {
@Bean
public Audience audience() {
return new Audience();
}
}
測試:
下面繼續展示環繞通知的用法:
@Around("performance()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("看錶演之前,觀衆將收集調成靜音");
System.out.println("觀衆入席坐好");
proceedingJoinPoint.proceed();
System.out.println("演出結束觀衆鼓掌 !!");
}catch (Throwable e){
System.out.println("演出失敗,觀衆要求退款!!!");
}
}
下面繼續展示處理通知中的參數:
連接點變成:
切點變成:
切面變成:
測試:
繼續演示通過註解引入新的功能,如果一個切面能夠爲一個方法增加新的功能,爲什麼能爲一個對象增加新的功能呢?利用引入的AOP概念,切面可以爲Spring Bean增加新的方法。特別是沒有源碼控制權的時候。
要引入表演類的新方法:
新寫一個切面:加號表示接口下的所有實現。以及引入接口方法的
配置注入Bean
使用
結果:
Spring AOP的演示到此爲止,如果要更加強大的AOP,支持更多的類型那就需要AspectJ,例如當我們創建對象時候可以增加構造器通知,對象屬性的改變也可以通知等等衆多的類型。
4.Spring AOP的原理:
用到的設計模式兩種:代理模式,責任鏈模式,動態代理。
首先是織入的時機,對於Spring來講,AOP織入的時機是運行期。
代理:
動態代理:java基礎--19動態代理
代理的方式有兩種,JDK和CGLib,那麼Spring AOP 選擇的是什麼代理方式呢?
Spring 是如何創建出代理的bean呢?
如何強制使用CGlib的代理:
然後我們再回答一個問題,多個AOP調用時如何疊加在一起的,答案是採用了責任鏈的模式
在Spring 啓動的時候,運行期,Spring就會掃描到帶有@Aspect註解的切面類,然後根據切點的表達式匹配出所有的連接點,然後會判斷這個目標對象是接口實現還是繼承實現,然後就可以確定使用JDK還是CGLib的代理方式生成代理類。順便會判斷通知的類型,最後調用的時候當然就是調用代理類啦。