面向切面編程的基本原理
DI有助於應用對象之間的解耦,而AOP可以實現橫切關注點與他們所影響對象之間的解耦。
1.什麼是面向切面編程
切面能夠幫助我們模塊化橫切關注點。橫切關注點可以被描述爲影響應用多處的功能。安全就是一個橫切關注點
定義AOP術語
通知:定義了切面是什麼,以及何時使用,除了描述切面要完成的工作,通知還解決了何時執行這個工作的問題,他應該用在某個方法被調用之前/之後/之前之後都調用,還是方法拋出異常時調用
Spring切面可以應用5鍾類型的通知
- 前置通知
- 後置通知
- 返回通知
- 異常通知
- 環繞通知
連接點——連接點是在應用執行過程中能夠插入切面的一個點。這個點可以是調用方法時、拋出異常時、甚至修改一個字段時。切面代碼可以利用這些點插入到應用的正常流程之中,並添加新的行爲。
切點——一個切面並不需要通知應用的所有連接點。切點有助於縮小切面所通知的連接點的範圍。
通知定義了切面的“什麼”和“何時”的話,那麼切點就定義了“何處”。
切面——是通知和切點的結合.通知和切面共同定義了切面的全部內容——它是什麼,它在何時和何處完成其功能。
引入——允許我們向現有的類添加新的方法或屬性;創建一個通知類該類記錄了對象最後一次的修改狀態,需要一個方法和一個實例變量來保存這個狀態。然後這個新方法和新實例變量就可以引入到現有類中,從而無需修改這些現有類的情況下,讓他們具有新的行爲和狀態。
織入——把切面應用到目標對象並創建新的代理對象的過程。切面在指定的連接點被織入到目標對象中。在目標對象的聲明週期裏有多個點可以進行織入。
Spring提供了4種類型的AOP支持
- 基於代理的經典SpringAOP
- 純POJO切面
- @AspectJ註解驅動的切面;
- 注入式AspectJ切面(適用於Spring各版本)
前三種都是AOP實現的變體,SpringAOP構建在動態代理的基礎之上,因此,Spring對AOP的支持侷限於方法的攔截
Spring在運行時通知對象
通過在代理類中包裹對象,Spring在運行期間把切面織入到Spring管理的Bean中。代理類封裝了目標類,並攔截被通知方法的調用,再把調用轉發給真正的目標bean。當代理攔截到方法調用時,在調用目標Bean方法之前,會執行切面邏輯。
直到應用需要被代理的bean時,Spring才創建代理對象。如果使用 的是ApplicationContext的話,在ApplicationContext從BeanFactory中加載所有bean的時候,Spring纔會創建被代理的對象。因爲Spring運行時才創建代理對象,所以我們不需要特殊的編譯器來織入AOP的切面。
Spring只支持方法級別的連接點
通過各種AOP方案可以支持多種連接點模型。因爲Spring基於動態代理,所以Spring只支持方法連接點。
通過切點來選擇連接點
在SpringAOP中,要是用AspectJ的切點表達式語言來定義切點。
SpringAOP 所支持的AspectJ切點指示器
我們注意到只有execution指示器是實際執行匹配的,而其他的指示器都是用來顯示匹配的。execution指示器是我們在編寫切點定義時最主要使用的指示器。
編寫切點
爲了闡述Spring中的切面,我們需要有個主題來定義切面的切點。
定義切點表達式
使用註解創建切面
AspectJ提供了無個註解來定義通知
如果你就此止步的話,Audience只會是Spring容器中的一個bean,即便使用了AspectJ註解它也不會被視爲切面,這些註解不會解析,也不會創建其轉換爲切面的代理。
創建環繞通知
處理通知中的參數