什么是Spring的AOP特性?
我工作遇到的第一個(gè)問題就是用 Spring AOP 解決的。Spring AOP 真正用起來的時(shí)候很少,但是無一不是解決重要問題。用一種輕松的手法解決了重要的問題,Spring AOP 做到了。
??
Spring AOP 的登場
在工作中經(jīng)常會遇到維護(hù)老 WEB 項(xiàng)目的任務(wù),老項(xiàng)目有很多問題,其中一個(gè)就是沒有日志系統(tǒng),出現(xiàn)問題,排查困難。當(dāng)時(shí)我的任務(wù)就是給老項(xiàng)目增加日志。按理來說,增加日志不難,增加 Log4j 依賴,填好配置。在每個(gè) Controller 類和 Server 類里創(chuàng)建日志對象,然后在關(guān)鍵位置上加上日志打印就行。
問題在于,項(xiàng)目已經(jīng)寫好了,總共大好幾千的方法一個(gè)個(gè)加日志打印,人要累吐血,而且這屬于重復(fù)工作,太痛苦了。于是就想到了使用 Spring AOP 添加日志,果然輕易的解決了問題。
??
什么是 Spring AOP
現(xiàn)在進(jìn)入正題,首先介紹什么是 Spring AOP。官方介紹是面向切面編程。首先這是一種編程思想,基于面向?qū)ο缶幊蹋∣OP)的一種補(bǔ)充。面向?qū)ο缶幊趟枷胧侵溉f物皆對象。處理對象的過程叫方法,面向切面編程就是指把方法看成一個(gè)整體,在不改變方法原代碼的情況下改變方法執(zhí)行過程。
打個(gè)比方就是番茄夾梅子。先把番茄切開,里面放一個(gè)梅子,然后把番茄合上,番茄還是那個(gè)番茄,沒有變,但是里面有了梅子的味道。在物理層面,番茄已經(jīng)改變了,里面多了個(gè)梅子。但是變成代碼的時(shí)候,我們可以在不改變方法源代碼的情況下,改變方法運(yùn)行邏輯。

??
Spring AOP 原理
這種神奇的效果是怎么實(shí)現(xiàn)的呢?這個(gè)要?dú)w功于 23 種設(shè)計(jì)模式中的代理模式。要理解面向切面編程的原理,必須要先理解代理模式。
代理模式理解起來很簡單,打個(gè)比方就明白了。比如說你是彭于晏(讀者人均彭于晏),但是你只專注于表演這個(gè)能力,只能拿到演戲的錢。現(xiàn)在你特別出名,好多公司找你做代言人。但是你沒空去洽談。這個(gè)時(shí)候你就需要一個(gè)經(jīng)紀(jì)人,經(jīng)紀(jì)人會幫你接代言,幫你管理粉絲,幫你接戲。你的工作還是沒變,但是收入增加了。
在這個(gè)過程中,“彭于晏”代表的是原生對象。而全權(quán)代表“彭于晏”的經(jīng)紀(jì)人被稱為代理對象。當(dāng)我需要“彭于晏”表演的時(shí)候,我去找經(jīng)紀(jì)人。這個(gè)過程就是代理模式。
流程圖:

代理模式的兩種常見實(shí)現(xiàn)方法:動態(tài)代理、靜態(tài)代理
先說靜態(tài)代理:靜態(tài)代理的優(yōu)點(diǎn)是,好理解,好觀察。缺點(diǎn)是難維護(hù),死板。不適合在動態(tài)的項(xiàng)目需求中使用。
簡易版靜態(tài)代理:



這就是靜態(tài)代理,目標(biāo)對象和代理對象都需要實(shí)現(xiàn)自己的父類方法。一旦父類增加或修改了,需要在所有子類中一起變動,維護(hù)十分困難。所以一般在項(xiàng)目中很少使用靜態(tài)代理。
再說動態(tài)代理:動態(tài)代理的優(yōu)點(diǎn)是:好使用,好維護(hù)。缺點(diǎn)是:不好理解,不好觀測。現(xiàn)在上代碼:
簡易版動態(tài)代理:接口部分不變,“彭于晏”部分不變

注意接下來的代理對象


所謂動態(tài)代理就是借用反射來創(chuàng)建代理對象,借用反射來創(chuàng)建代理對象的好處就是通用性極高。這樣就避免了上層接口改變,代理對象也要修改代碼這一蛋疼行為。
??
Spring AOP 上手使用
現(xiàn)在明白了 Spring AOP 是干啥的,接下來展示,Spring AOP 在實(shí)際項(xiàng)目中的使用。Spring AOP 已經(jīng)實(shí)現(xiàn)了自動創(chuàng)建動態(tài)代理,我們只需要學(xué)會正確調(diào)用即可。
圖文展示:
第一步:導(dǎo)入 Spring AOP 依賴

PS:加入新依賴后要更新依賴
第二步:使用切面注解@Aspect

切面:定義當(dāng)前類是切面類,需要給每一個(gè)滿足切面條件的類生成不同的代理對象。
第三步:定義需要的通知。

通知:通知就是定義代理對象的代碼要在什么時(shí)候生效。
以下是常用通知類型,可以根據(jù)實(shí)際需要選用通知

第四步:填寫需要的切面表達(dá)式

切面表達(dá)式:定義了滿足什么條件就去生成其代理類。
整理常用切點(diǎn)表達(dá)式:

執(zhí)行結(jié)果:

??
Spring AOP 的優(yōu)勢和缺點(diǎn)
Spring AOP 的優(yōu)勢很明顯,在不改變原代碼的情況下,加入新的邏輯代碼。缺點(diǎn)是,邏輯不連貫,閱讀體驗(yàn)不好。畢竟這是專門為解決特定問題而出現(xiàn)的專用工具。
我們應(yīng)該有一個(gè)意識,當(dāng)我們需要批量給方法新增邏輯的時(shí)候,要能想起 Spring AOP。
Java 里面概念很多,知識點(diǎn)也很多。很多概念和知識點(diǎn)是專為解決特定問題而誕生的,我們不可能記住全部知識點(diǎn),但是在需要用到一個(gè)知識點(diǎn)的時(shí)候,要能想起什么知識點(diǎn)能解決這個(gè)問題,在不斷的遇到問題,解決問題的過程中,我們對這些知識點(diǎn)的理解自然會更深刻,但是不要停止腳步,要多想原理和為什么,這是通往架構(gòu)師的道路。
??
Spring AOP 總結(jié)
回顧一下本章重點(diǎn):
AOP 是一種編程思想——面向切面編程
AOP 實(shí)現(xiàn)原理——代理模式。代理模式分為動態(tài)代理和靜態(tài)代理。
Spring AOP 使用步驟:1.導(dǎo)入依賴。2.使用切面注釋。3.使用通知注釋。4.使用切點(diǎn)申明表達(dá)式。
都看到這里了。英俊瀟灑的小哥哥,貌美如花小姐姐,看完記得順手點(diǎn)贊。
