Spring之AOP
本文來介紹Spring的AOP。
為什麽使用AOP?
使用純面向對象的思想進行編程。那麽對象不但須要處理自身要負責的業務邏輯,要須要關心日誌、安全控制和事務。例如以下圖:
圖1
對遍布系統的關註點服務的調用,常常很分散。如日誌和安全。
AOP使這些服務模塊化,並以聲明的方式將它們應用到它們須要影響的組件中去。結果使這些組件具有高內聚以及更加關註自身業務,全然不須要了解可能涉及的系統服務的復雜性。
所以:AOP確保POJO保持簡單,AOP是OOP的最好的補充與完好。
利用AOP,我們能夠使用各種功能層去包裹核心業務層。
這些層以聲明的方式靈活應用到你的系統中,甚至你的核心應用根本不知道它們的存在。
這是一個很強大的理念,能夠將安全、事務和日誌關註點與核心業務分離。
例如以下圖:
圖2
利用AOP。遍布系統的關註點覆蓋在它們所應用的組件之上。促使應用組件僅僅需關註它們的核心業務功能。
AOP
AOP有自己術語。雖然這些術語不是非常直接,可是我們要逐步了解它們。
Cross Cutting Concern橫切關註點
橫切性關註點,就是要動態運行的方法,它會遍布在系統的處理流程中。
Aspect切面
對橫切性關註點的模塊化。
且面試通知和切點的結合。通知和切點共同定義了關於切面的所有內容——它是什麽。在何時何處完畢其功能。
Advice通知
對橫切性關註點的詳細實現。通知定義了切面是什麽,以及何時使用。此外,通知還決定了什麽時候運行工作的問題。是在應用某個方法被調用之前(Before)、之後(After)、成功運行後(After-returning)、異常(After-throwing)和Around(被通知的方法調用前後)。
JoinPoint連接點
Advice在應用程序上運行的點或時機。Spring僅僅支持方法的連接。這個點也能夠使屬性改動。如Aspectj。
連接點是應用運行過程中鞥能夠插入切面的一個點。這個店能夠使調用方法時、拋出異常時、甚至改動一個字段時。切面代碼能夠利用這些點插入到應用的正常流程之中,並加入新的行為。這些操作,都在編譯前完畢。
Pointcut切點
定義了Advice應用到哪些連接點上,對Spring來說就是方法調用。切面定義了“什麽”和“何時”,切點定義了“何處”。
切點的定義會匹配同誌全部織入的一個或多個連接點。我們通常使用明白的類和方法名稱來指定這些切點。或是利用正則匹配類和方法名稱模式來指定這些切點。有些AOP框架同意我們動態的切點,能夠依據執行時的決策(如方法的參數值)來決定是否應用通知。
Weave織入
將Advice應用到Target Object的過程。
Spring支持動態織入。
在目標對象的生命周期裏多個點能夠進行織入:
編譯期——切面在目標類編譯時被織入。
AspectJ的織入就是這樣的方式;
類載入期——切面在目標類載入到JVM時被織入。這樣的方式須要ClassLoader,能夠再目標類被引入應用之前增強目標類的字節碼。
執行期——切面在應用執行的某個時刻被織入。
在織入切面時,AOP容器會為目標對象動態創建一個代理對象。這是Spring AOP的織入方式。
Proxy
Spring的AOP默認使用JDK的動態代理,它的代理是執行時創建的。也能夠使用CGLIB代理。
Introduction
能夠動態的為類加入方法。
Spring的AOP
眼下AOP已經形成了三足鼎立。
AspectJ、Jboss AOP和Spring的AOP。
這裏,我們註重介紹Spring的AOP。
Spring僅僅支持方法連接點。應為Spring基於動態代理,所以Spring僅僅支持方法連接點。
而AspectJ和JBoss的AOP,除了方法切點。還提供了字段和構造器接入點。Spring缺少對字段連接點的支持。
無法讓我們創建細粒度的通知。
因為。SpringAOP對方法的支持,就已經足夠了。假設還不能滿足,能夠考慮使用AspectJ來輔助實現。這裏。我們重點介紹動態代理方式的AOP。
AOP的內部實現
Spring的AOP默認使用JDK的動態代理,同一時候。也支持CGLIB的代理。
JDK動態代理。採用反射機制動態創建的。動態生成了字節碼。僅僅是他生成的字節碼的方式必須和接口綁定。
JDK動態代理源代碼剖析:JDK動態代理實現原理
JDK的動態代理有非常大限制。這樣的方法要求業務類必須實現一個業務接口。
即。僅僅有以下情況,才幹使用JDK的動態代理:
而CGlib引用第三方包asm.jar,採用字節碼技術。
通過字節碼技術為須要代理的類創建一個子類,並在子類中採用方法攔截的技術攔截全部父類方法的調用,並織入橫切邏輯。
CGlib採用繼承的方式,繼承指定的類。對指定的類生成一個子類。覆蓋其全部方法。
這樣的方式,不管有無接口。都可以對其進行代理。如以下兩種情況:
CGLIB創建動態代理對象性能比JDK創建的動態代理對象性能高非常多,可是CGLIB在創建代理對象時所花費的時間卻比JDK多非常多。所以對於單例的對象,無需頻繁的創建對象,使用CGlib比較合適;則反,假設須要頻繁創建對象,考慮使用JDK代理。
本文總結了Spring中AOP的相關內容、AOP的相關術語以及內部實現。
詳細實現就不往外貼了,比較簡單。
有興趣的童鞋能夠在以下留言,一起討論一下。
Spring之AOP