Spring - AOP簡單理解及術(shù)語解釋

工作中使用Spring Boot將近一年了,由于某些需要也接觸過Spring Cloud。Spring到Spring Boot再到Spring Cloud,逐漸地變成了一套完整的企業(yè)分布式系統(tǒng)的解決方案,已經(jīng)不能單純的認(rèn)為是基于Spring的一套快速配置腳手架了。雖說如此,但是兩者都脫離不開Spring最基本的兩個概念:IOC和AOP。也因此,如果希望更加了解和掌握Spring,這兩個概念必須學(xué)習(xí)一下,本篇會簡單介紹下AOP的思想,主要基于《Spring實戰(zhàn)(第四版)》中的相關(guān)章節(jié)與一些個人理解。?


什么是AOP

簡單一句話概括:在運行時,動態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想。

上面的概括可以通俗的了解到什么是AOP,但是并不嚴(yán)謹(jǐn),AOP不一定都在運行時生成代理對象來織入的,也可以在編譯期,類加載期織入,這一點Spring AOP和AspectJ就不完全相同。


為什么要有AOP

AOP是對OOP(面向?qū)ο缶幊蹋┑难a充和完善,當(dāng)一個集合有大量的公共行為和屬性時,我們可以通過封裝,繼承,多態(tài)等來表明集合內(nèi)對象的層次結(jié)構(gòu)。我們最常說的,實現(xiàn)一個父類,然后子類繼承它,父類/子類也可以很好的說明,OOP使得我們可以很好的定義一個集合內(nèi)元素的縱向關(guān)系,減少代碼的冗余,提高復(fù)用性,易擴展性。然而對于某些橫向的關(guān)系,OOP并不能很好的滿足,就會出現(xiàn)大量的重復(fù)代碼,各個模塊的復(fù)用性也會降低。

舉個例子: 有三個人爺爺,爸爸和兒子,自然就是兒子繼承爸爸,爸爸繼承爺爺,這三者一生都會經(jīng)歷出生,入學(xué),工作,結(jié)婚等等一系列人生階段。現(xiàn)在當(dāng)我們需要記錄這三者的每個人生階段發(fā)生的時間節(jié)點,只能在每個階段發(fā)生時刻記錄一下,這就是最簡單的日志功能。必然會導(dǎo)致代碼的重復(fù)性,并且以“入學(xué)”為例,“入學(xué)”應(yīng)該只需要知道入學(xué)本身的步驟,比如:體檢,面試,交學(xué)費。而不是: 記錄開始時間,體檢,面試,交學(xué)費,記錄結(jié)束時間。日志功能對于各個函數(shù)都應(yīng)該是非透明的,函數(shù)本身只需要實現(xiàn)核心關(guān)注點即業(yè)務(wù)邏輯本身,這些散落在各個方法核心功能上,卻又與核心業(yè)務(wù)邏輯無關(guān)的功能,便是橫切關(guān)注點。

簡而言之,我們把那些與業(yè)務(wù)邏輯無關(guān)的,卻被各個業(yè)務(wù)模塊大量調(diào)用的邏輯給封裝起來,進而便于減少系統(tǒng)的重復(fù)代碼量,并且能夠降低模塊間的耦合度,并有利于未來的擴展和維護,降低了維護成本。最重要的我認(rèn)為,各個函數(shù)本身只關(guān)注了核心業(yè)務(wù)邏輯。


AOP術(shù)語以及解釋

1)連接點(Joinpoint)

? ? 程序執(zhí)行的某個特定位置:如類開始初始化前、類初始化后、類某個方法調(diào)用前、調(diào)用后、方法拋出異常后。一個類或一段程序代碼擁有一些具有邊界性質(zhì)的特定點,這些點中的特定點就稱為“連接點”。Spring僅支持方法的連接點,即僅能在方法調(diào)用前、方法調(diào)用后、方法拋出異常時以及方法調(diào)用前后這些程序執(zhí)行點織入通知。連接點由兩個信息確定:第一是用方法表示的程序執(zhí)行點;第二是用相對點表示的方位。

? ? 2)切點(Pointcut)

? ? 每個程序類都擁有多個連接點,如一個擁有兩個方法的類,這兩個方法都是連接點,即連接點是程序類中客觀存在的事物。AOP通過“切點”定位特定的連接點。連接點相當(dāng)于數(shù)據(jù)庫中的記錄,而切點相當(dāng)于查詢條件。切點和連接點不是一對一的關(guān)系,一個切點可以匹配多個連接點。

? ? 連接點是一個比較空泛的概念,就是定義了哪一些地方是可以切入的,也就是所有允許你通知的地方。

? ? 切點就是定義了通知被應(yīng)用的位置 (配合通知的方位信息,可以確定具體連接點)

? ? 3)通知(Advice)

? ? 通知是織入到目標(biāo)類連接點上的一段程序代碼,在Spring中,通知除用于描述一段程序代碼外,還擁有另一個和連接點相關(guān)的信息,這便是執(zhí)行點的方位。結(jié)合執(zhí)行點方位信息和切點信息,我們就可以找到特定的連接點。

Spring切面可以應(yīng)用5種類型的通知:

????????前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;

????????后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時不會關(guān)心方法的輸出是什么;

????????返回通知(After-returning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;

? ? ? ? 異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知;

????????環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為。

? ? ? ? 通知就定義了,需要做什么,以及在某個連接點的什么時候做。 上面的切點定義了在哪里做。

? ? 4)目標(biāo)對象(Target)

? ? 通知邏輯的織入目標(biāo)類。如果沒有AOP,目標(biāo)業(yè)務(wù)類需要自己實現(xiàn)所有邏輯,而在AOP的幫助下,目標(biāo)業(yè)務(wù)類只實現(xiàn)那些非橫切邏輯的程序邏輯,而性能監(jiān)視和事務(wù)管理等這些橫切邏輯則可以使用AOP動態(tài)織入到特定的連接點上。

? ? 5)引介(Introduction)

? ? 引介是一種特殊的通知,它為類添加一些屬性和方法。這樣,即使一個業(yè)務(wù)類原本沒有實現(xiàn)某個接口,通過AOP的引介功能,我們可以動態(tài)地為該業(yè)務(wù)類添加接口的實現(xiàn)邏輯,讓業(yè)務(wù)類成為這個接口的實現(xiàn)類。??

? ? 允許向現(xiàn)有類中添加方法和屬性(通知中定義的)

? ? 6)織入(Weaving)

? ? 織入是將通知添加對目標(biāo)類具體連接點上的過程。AOP像一臺織布機,將目標(biāo)類、通知或引介通過AOP這臺織布機天衣無縫地編織到一起。根據(jù)不同的實現(xiàn)技術(shù),AOP有三種織入的方式:

? ? a、編譯期織入,這要求使用特殊的Java編譯器。

? ? b、類裝載期織入,這要求使用特殊的類裝載器。

? ? c、動態(tài)代理織入,在運行期為目標(biāo)類添加通知生成子類的方式。

? ? 把切面應(yīng)用到目標(biāo)對象來創(chuàng)建新的代理對象的過程,Spring采用動態(tài)代理織入,而AspectJ采用編譯期織入和類裝載期織入。

? ? 7)代理(Proxy)

? ? 一個類被AOP織入通知后,就產(chǎn)出了一個結(jié)果類,它是融合了原類和通知邏輯的代理類。根據(jù)不同的代理方式,代理類既可能是和原類具有相同接口的類,也可能就是原類的子類,所以我們可以采用調(diào)用原類相同的方式調(diào)用代理類。

? ? 8)切面(Aspect)

? ? 切面由切點和通知組成,它既包括了橫切邏輯的定義,也包括了連接點的定義,Spring AOP就是負責(zé)實施切面的框架,它將切面所定義的橫切邏輯織入到切面所指定的連接點中。

? ? 切點的通知的結(jié)合,切面知道所有它需要做的事:何時/何處/做什么


本文介紹的比較簡單,單純的介紹了一下AOP的概念,至于如何聲明切面,定義切點等等,有時間會寫一個小demo分享。

我所有文章的個人理解和舉例都可能存在偏差以及錯誤,歡迎指正。另外如果有想指正,探討,提問,都歡迎評論。我都會盡我所能一一回復(fù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容