本文將爲各位帶來 Spring 的另一個重點知識點 —— Spring AOP。關注我的公衆號「Java面典」,每天 10:24 和你一起了解更多 Java 相關知識點。
什麼是 AOP
面向切面編程(aspect-oriented programming),是一種將橫切關注點與業務邏輯分離的編程方式。每個橫切關注點都集中在一個地方,而不是分散在多處代碼中。這樣使我們的服務模塊更加簡潔,因爲它們只包含了主要關注點的代碼,而次要的功能或者說輔助的功能被轉移到切面中了。
AOP 主要應用場景有:
- Authentication 權限
- Caching 緩存
- Context passing 內容傳遞
- Error handling 錯誤處理
- Lazy loading 懶加載
- Debugging 調試
- logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準
- Performance optimization 性能優化
- Persistence 持久化
- Resource pooling 資源池
- Synchronization 同步
- Transactions 事務
AOP 核心知識點
主要術語
- Aspect(切面):切入業務流程的一個獨立模塊,在一個應用程序可以擁有任意數量的切面。如事務管理,就是切面的一個應用例子;
- Join point(連接點):業務流程在運行過程中需要插入切面的具體位置。如執行某個特定方法或者處理異常的時候;
- Advice(通知):是切面的具體實現方法。可分爲前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)和環繞通知(Around)五種。實現方法具體屬於哪類通知,是在配置文件和註解中指定的;
- Pointcut(切入點):用於定義通知應該切入到哪些連接點上,不同的通知通常需要切入到不同的連接點上;
- Target(目標對象):被一個或者多個切面所通知的對象;
- Proxy(代理對象):將通知應用到目標對象之後被動態創建的對象。可以簡單地理解爲,代理對象爲目標對象的業務邏輯功能加上被切入的切面所形成的對象;
- Weaving(切入):將切面應用到目標對象從而創建一個新的代理對象的過程。這個過程可以發生在編譯期、類裝載期及運行期。
通知類型
Spring AOP 主要有五種通知類型,分別是前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)和環繞通知(Around):
- Before(前置通知):在連接點之前執行的通知,但這個通知不能阻止連接點之前的執行流程(除非它拋出一個異常);
- AfterReturning(後置通知):在連接點正常執行完成之後的通知;
- AfterThrowing(異常通知):在連接點方法拋出異常時執行的通知;
- After(最終通知):在連接點執行完成之後的通知(無論是正常完成,還是拋出異常退出執行);
- Around(環繞通知):可以在連接點執行前後都執行的通知。
AOP 的兩種代理方式
Spring 提供了兩種方式來生成代理對象: JDKProxy 和 Cglib,具體使用哪種方式生成由 AopProxyFactory 根據 AdvisedSupport 對象的配置來決定。默認的策略是如果目標類是接口,則使用 JDK 動態代理技術,否則使用 Cglib 來生成代理。
JDK 動態接口代理
JDK 動態代理主要涉及到 java.lang.reflect 包中的兩個類:Proxy 和 InvocationHandler。InvocationHandler是一個接口,通過實現該接口定義橫切邏輯,並通過反射機制調用目標類的代碼,動態將橫切邏輯和業務邏輯編制在一起。Proxy 利用 InvocationHandler 動態創建一個符合某一接口的實例,生成目標類的代理對象。
CGLib 動態代理
CGLib 全稱爲 Code Generation Library,是一個強大的高性能,高質量的代碼生成類庫,可以在運行期擴展 Java 類與實現 Java 接口,CGLib 封裝了 asm,可以再運行期動態生成新的 class。和 JDK 動態代理相比較:JDK 創建代理有一個限制,就是隻能爲接口創建代理實例,而對於沒有通過接口定義業務方法的類,則可以通過 CGLib 創建動態代理。