Spring AOP基本概念
舉個(gè)栗子給大家講一下代理:
我相信大家都知道明星吧。
大部分明星是都有經(jīng)紀(jì)人的。
假如我們是一個(gè)大廠,現(xiàn)在想要找一個(gè)明星代理產(chǎn)品,那我們會直接找到明星嗎?不?,F(xiàn)實(shí)中,你大部分找到的都是找到明星的代理人(經(jīng)紀(jì)人)。經(jīng)紀(jì)人通過和你約談,了解產(chǎn)品,看自己的家明星,是否可以接下這個(gè)廣告。覺得可以,就會和你商量簽訂合同、商談活動(dòng)日期、排練等等。 雖然商家知道自己并沒有找到明星,但是他卻知道這件事情已經(jīng)成了。
1、在這個(gè)流程中,商家找了明星的經(jīng)紀(jì)人。但是卻完成了最初的任務(wù)。
2、明星經(jīng)紀(jì)人 幫明星簽訂合同、訂下活動(dòng)日期等等。
3、明星專注于拍廣告。
這個(gè)時(shí)候我們是不是就可以講 明星經(jīng)紀(jì)人增強(qiáng)了明星的功能勒?
什么是AOP?
與OOP對比,AOP是處理一些橫切行問題。這些橫切性問題不會影響到主邏輯的實(shí)現(xiàn),但是會散落到代碼的各個(gè)部分,難以維護(hù)。AOP就是把這些問題和主業(yè)務(wù)邏輯分開,達(dá)到與主業(yè)務(wù)邏輯解耦的目的。
AOP是一種面向切面的編程思想。這些橫切性問題,把它們抽象為一個(gè)切面,關(guān)注點(diǎn)在切面的編程,這就是所謂的AOP。
AOP關(guān)注點(diǎn)是橫切性問題:
基本術(shù)語
(1)切面(Aspect)
跨越多個(gè)類的關(guān)注點(diǎn)的模塊化。事務(wù)管理是Java 應(yīng)用程序中橫切關(guān)注點(diǎn)的一個(gè)很好的例子。在 Spring AOP 中,方面是通過使用常規(guī)類(基于模式的方法)或使用@Aspect
注解注解的常規(guī)類 (@AspectJ 風(fēng)格)實(shí)現(xiàn)的。
切面是一個(gè)橫切關(guān)注點(diǎn)的模塊化,一個(gè)切面能夠包含同一個(gè)類型的不同增強(qiáng)方法,比如說事務(wù)處理和日志處理可以理解為兩個(gè)切面。切面由切入點(diǎn)和通知組成,它既包含了橫切邏輯的定義,也包括了切入點(diǎn)的定義。 Spring AOP就是負(fù)責(zé)實(shí)施切面的框架,它將切面所定義的橫切邏輯織入到切面所指定的連接點(diǎn)中。
可以簡單地認(rèn)為, 使用 @Aspect 注解的類就是切面
(2) 目標(biāo)對象(Target)
目標(biāo)對象指將要被增強(qiáng)的對象,即包含主業(yè)務(wù)邏輯的類對象?;蛘哒f是被一個(gè)或者多個(gè)切面所通知的對象。
(3) 連接點(diǎn)(JoinPoint)
程序執(zhí)行過程中明確的點(diǎn),如方法的調(diào)用或特定的異常被拋出。連接點(diǎn)由兩個(gè)信息確定:
- 方法(表示程序執(zhí)行點(diǎn),即在哪個(gè)目標(biāo)方法)
- 相對點(diǎn)(表示方位,即目標(biāo)方法的什么位置,比如調(diào)用前,后等)
簡單來說,連接點(diǎn)就是被攔截到的程序執(zhí)行點(diǎn),因?yàn)镾pring只支持方法類型的連接點(diǎn),所以在Spring中連接點(diǎn)就是被攔截到的方法。
講人話 就是spring允許你使用通知的地方
(4) 切入點(diǎn)(PointCut)
上面說的連接點(diǎn)的基礎(chǔ)上,來定義切入點(diǎn),你的一個(gè)類里,有15個(gè)方法,那就有幾十個(gè)連接點(diǎn)了對把,但是你并不想在所有方法附近都使用通知(使用叫織入,以后再說),你只想讓其中的幾個(gè),在調(diào)用這幾個(gè)方法之前,之后或者拋出異常時(shí)干點(diǎn)什么,那么就用切點(diǎn)來定義這幾個(gè)方法,讓切點(diǎn)來篩選連接點(diǎn),選中那幾個(gè)你想要的方法。
@Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))") public void pointcut() { }
上邊切入點(diǎn)的匹配規(guī)則是com.remcarpediem.test.aop.service
包下的所有類的所有函數(shù)。
(5) 通知(Advice)
Spring AOP 包括以下類型的通知:
- 前通知(Before advice):在連接點(diǎn)之前運(yùn)行的通知,但沒有能力阻止執(zhí)行流繼續(xù)到連接點(diǎn)(除非它拋出異常)。
- 返回后通知(After returning advice):在連接點(diǎn)正常完成后運(yùn)行的通知(例如,如果方法返回而沒有拋出異常)。
- 拋出異常通知后(After throwing advice):如果方法通過拋出異常退出,則運(yùn)行通知。
- After (finally) 通知(After (finally) advice):不管連接點(diǎn)退出的方式(正?;虍惓7祷兀┒紝⑦\(yùn)行的通知。
- 環(huán)繞通知(Around advice):環(huán)繞連接點(diǎn)的通知,例如方法調(diào)用。這是最有力的建議。環(huán)繞通知可以在方法調(diào)用前后執(zhí)行自定義行為。它還負(fù)責(zé)選擇是繼續(xù)連接點(diǎn)還是通過返回自己的返回值或拋出異常來縮短建議的方法執(zhí)行。
// @Before說明這是一個(gè)前置通知,log函數(shù)中是要前置執(zhí)行的代碼,JoinPoint是連接點(diǎn), @Before("pointcut()") public void log(JoinPoint joinPoint) { }
(6) 織入(Weaving)
織入是將切面和業(yè)務(wù)邏輯對象連接起來, 并創(chuàng)建通知代理的過程??椚肟梢栽诰幾g時(shí),類加載時(shí)和運(yùn)行時(shí)完成。在編譯時(shí)進(jìn)行織入就是靜態(tài)代理,而在運(yùn)行時(shí)進(jìn)行織入則是動(dòng)態(tài)代理。
關(guān)鍵就是:切點(diǎn)定義了哪些連接點(diǎn)會得到通知
靜態(tài)代理模式
所謂靜態(tài)代理就是AOP框架會在編譯階段生成AOP代理類,因此也稱為編譯時(shí)增強(qiáng)。ApsectJ是靜態(tài)代理的實(shí)現(xiàn)之一,也是最為流行的。靜態(tài)代理由于在編譯時(shí)就生成了代理類,效率相比動(dòng)態(tài)代理要高一些。AspectJ可以單獨(dú)使用,也可以和Spring結(jié)合使用。
動(dòng)態(tài)代理模式
與靜態(tài)代理不同,動(dòng)態(tài)代理就是說AOP框架不會去修改編譯時(shí)生成的字節(jié)碼,而是在運(yùn)行時(shí)在內(nèi)存中生成一個(gè)AOP代理對象,這個(gè)AOP對象包含了目標(biāo)對象的全部方法,并且在特定的切點(diǎn)做了增強(qiáng)處理,并回調(diào)原對象的方法。
Spring AOP中的動(dòng)態(tài)代理主要有兩種方式:JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理。
JDK代理通過反射來處理被代理的類,并且要求被代理類必須實(shí)現(xiàn)一個(gè)接口。核心類是 InvocationHandler接口 和 Proxy類。
而當(dāng)目標(biāo)類沒有實(shí)現(xiàn)接口時(shí),Spring AOP框架會使用CGLIB來動(dòng)態(tài)代理目標(biāo)類。
CGLIB(Code Generation Library
),是一個(gè)代碼生成的類庫,可以在運(yùn)行時(shí)動(dòng)態(tài)的生成某個(gè)類的子類。CGLIB是通過繼承的方式做的動(dòng)態(tài)代理,因此如果某個(gè)類被標(biāo)記為final,那么它是無法使用CGLIB做動(dòng)態(tài)代理的。核心類是 MethodInterceptor 接口和Enhancer 類
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring?Security實(shí)現(xiàn)接口放通的方法詳解
在用Spring?Security項(xiàng)目開發(fā)中,有時(shí)候需要放通某一個(gè)接口時(shí),我們需要在配置中把接口地址配置上,這樣做有時(shí)候顯得麻煩。本文將通過一個(gè)注解的方式快速實(shí)現(xiàn)接口放通,感興趣的可以了解一下2022-05-05Java如何實(shí)現(xiàn)壓縮文件與解壓縮zip文件
這篇文章主要介紹了Java如何實(shí)現(xiàn)壓縮文件與解壓縮zip文件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12淺談Spring Data JPA與MyBatisPlus的比較
本文主要介紹了淺談Spring Data JPA 與 MyBatisPlus的比較2024-08-08Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之背包問題
背包問題是一個(gè)非常典型的考察動(dòng)態(tài)規(guī)劃應(yīng)用的題目,對其加上不同的限制和條件,可以衍生出諸多變種,若要全面理解動(dòng)態(tài)規(guī)劃,就必須對背包問題了如指掌2022-02-02java如何實(shí)現(xiàn)抽取json文件指定字段值
這篇文章主要介紹了java如何實(shí)現(xiàn)抽取json文件指定字段值,具有很好的參考價(jià)值,希望對大家有所幫助。2022-06-06