javascript
Spring AOP 面向切面编程
AOP
在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過(guò)預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。
在Spring中提供了面向切面編程的豐富支持,允許通過(guò)分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級(jí)服務(wù)(例如審計(jì)(auditing)和事務(wù)(transaction)管理)進(jìn)行內(nèi)聚性的開發(fā)。應(yīng)用對(duì)象只實(shí)現(xiàn)它們應(yīng)該做的——完成業(yè)務(wù)邏輯——僅此而已。它們并不負(fù)責(zé)(甚至是意識(shí))其它的系統(tǒng)級(jí)關(guān)注點(diǎn),例如日志或事務(wù)支持。
AOP使用場(chǎng)景
- Authentication 權(quán)限
- Caching 緩存
- Context passing 內(nèi)容傳遞
- Error handling 錯(cuò)誤處理
- Lazy loading 懶加載
- Debugging 調(diào)試
- logging, tracing, profiling and monitoring 記錄跟蹤 優(yōu)化 校準(zhǔn)
- Performance optimization 性能優(yōu)化
- Persistence 持久化
- Resource pooling 資源池
- Synchronization 同步
- Transactions 事務(wù)
AOP的術(shù)語(yǔ)
?
通知定義了切面是什么以及何時(shí)使用。描述了切面要完成的工作和何時(shí)需要執(zhí)行這個(gè)工作。
通知就是切面中除去切點(diǎn)之外的部分。如在方法執(zhí)行前觸發(fā),執(zhí)行后觸發(fā),異常時(shí)觸發(fā),以及觸發(fā)那個(gè)方法。
2.連接點(diǎn)(Joinpoint):
程序能夠應(yīng)用通知的一個(gè)"時(shí)機(jī)",這些"時(shí)機(jī)"就是連接點(diǎn),例如方法被調(diào)用時(shí)、異常被拋出時(shí)等等。
連接點(diǎn)是通知的一部分。
3.切入點(diǎn)(Pointcut)
通知定義了切面要發(fā)生的"故事"和時(shí)間,那么切入點(diǎn)就定義了"故事"發(fā)生的地點(diǎn),例如某個(gè)類或方法的名稱,spring中允許我們方便的用正則表達(dá)式來(lái)指定
切入點(diǎn)定義在哪些類的那些方法上執(zhí)行。
4.切面(Aspect)
通知和切入點(diǎn)共同組成了切面:時(shí)間、地點(diǎn)和要發(fā)生的"故事"
切面就時(shí)被標(biāo)注了@Aspect注解的整個(gè)類要做的功能。包含定義切點(diǎn),連接點(diǎn),以及要觸發(fā)的操作。
5.引入(Introduction)
引入允許我們向現(xiàn)有的類添加新的方法和屬性(Spring提供了一個(gè)方法注入的功能)
6.目標(biāo)(Target)
即被通知的對(duì)象,如果沒有AOP,那么它的邏輯將要交叉別的事務(wù)邏輯,有了AOP之后它可以只關(guān)注自己要做的事(AOP讓他做愛做的事)
目標(biāo)是概念吧 不應(yīng)該有目標(biāo)這種配置 因?yàn)槟繕?biāo)是在切點(diǎn)里通過(guò)表達(dá)式配置的。
7.代理(proxy)
應(yīng)用通知的對(duì)象,詳細(xì)內(nèi)容參見設(shè)計(jì)模式里面的代理模式
這也是個(gè)概念,是內(nèi)部實(shí)現(xiàn)的邏輯。代理是spring為了實(shí)現(xiàn)AOP為采用的一種方式。
8.織入(Weaving)
把切面應(yīng)用到目標(biāo)對(duì)象來(lái)創(chuàng)建新的代理對(duì)象的過(guò)程,織入一般發(fā)生在如下幾個(gè)時(shí)機(jī):
(1)編譯時(shí):當(dāng)一個(gè)類文件被編譯時(shí)進(jìn)行織入,這需要特殊的編譯器才可以做的到,例如AspectJ的織入編譯器
(2)類加載時(shí):使用特殊的ClassLoader在目標(biāo)類被加載到程序之前增強(qiáng)類的字節(jié)代碼
(3)運(yùn)行時(shí):切面在運(yùn)行的某個(gè)時(shí)刻被織入,SpringAOP就是以這種方式織入切面的,原理應(yīng)該是使用了JDK的動(dòng)態(tài)代理技術(shù)
看看另外一種解釋,更加通俗易懂:
- 什么是面向切面編程
橫切關(guān)注點(diǎn):影響應(yīng)用多處的功能(安全、事務(wù)、日志)
- 切面:
橫切關(guān)注點(diǎn)被模塊化為特殊的類,這些類稱為切面
優(yōu)點(diǎn):
每個(gè)關(guān)注點(diǎn)現(xiàn)在都集中于一處,而不是分散到多處代碼中?
服務(wù)模塊更簡(jiǎn)潔,服務(wù)模塊只需關(guān)注核心代碼。
AOP 術(shù)語(yǔ)
- 通知:?
定義:切面也需要完成工作。在 AOP 術(shù)語(yǔ)中,切面的工作被稱為通知。
工作內(nèi)容:通知定義了切面是什么以及何時(shí)使用。除了描述切面要完成的工作,通知還解決何時(shí)執(zhí)行這個(gè)工作。
Spring 切面可應(yīng)用的 5 種通知類型:
Before——在方法調(diào)用之前調(diào)用通知
After——在方法完成之后調(diào)用通知,無(wú)論方法執(zhí)行成功與否
After-returning——在方法執(zhí)行成功之后調(diào)用通知
After-throwing——在方法拋出異常后進(jìn)行通知
Around——通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為
- 連接點(diǎn):?
定義:連接點(diǎn)是一個(gè)應(yīng)用執(zhí)行過(guò)程中能夠插入一個(gè)切面的點(diǎn)。
連接點(diǎn)可以是調(diào)用方法時(shí)、拋出異常時(shí)、甚至修改字段時(shí)、
切面代碼可以利用這些點(diǎn)插入到應(yīng)用的正規(guī)流程中
程序執(zhí)行過(guò)程中能夠應(yīng)用通知的所有點(diǎn)。
- 切點(diǎn):?
定義:如果通知定義了"什么"和"何時(shí)"。那么切點(diǎn)就定義了"何處"。切點(diǎn)會(huì)匹配通知所要織入的一個(gè)或者多個(gè)連接點(diǎn)。
通常使用明確的類或者方法來(lái)指定這些切點(diǎn)。
作用:定義通知被應(yīng)用的位置(在哪些連接點(diǎn))
- 切面:?
定義:切面是通知和切點(diǎn)的集合,通知和切點(diǎn)共同定義了切面的全部功能——它是什么,在何時(shí)何處完成其功能。
- 引入:?
引入允許我們向現(xiàn)有的類中添加方法或?qū)傩?
- 織入:?
織入是將切面應(yīng)用到目標(biāo)對(duì)象來(lái)創(chuàng)建的代理對(duì)象過(guò)程。
切面在指定的連接點(diǎn)被織入到目標(biāo)對(duì)象中,在目標(biāo)對(duì)象的生命周期中有多個(gè)點(diǎn)可以織入
編譯期——切面在目標(biāo)類編譯時(shí)期被織入,這種方式需要特殊編譯器。AspectJ的織入編譯器就是以這種方式織入切面。
類加載期——切面在類加載到
JVM ,這種方式需要特殊的類加載器,他可以在目標(biāo)類被引入應(yīng)用之前增強(qiáng)該目標(biāo)類的字節(jié)碼。AspectJ5 的 LTW 就支持這種織入方式
運(yùn)行期——切面在應(yīng)用運(yùn)行期間的某個(gè)時(shí)刻被織入。一般情況下,在織入切面時(shí)候,AOP 容器會(huì)為目標(biāo)對(duì)象動(dòng)態(tài)的創(chuàng)建代理對(duì)象。Spring AOP 就是以這種方式織入切面。
?
Spring提供了4種實(shí)現(xiàn)AOP的方式:
可以說(shuō)上面123是Spring的AOP,第4個(gè)是AspectJ的了。關(guān)于Spring的AOP:
- Spring的通知是java類編寫的。AspectJ需要學(xué)習(xí)它自定義的語(yǔ)法。
- Spring在運(yùn)行時(shí)通知對(duì)象,而且不需要特殊的編譯器來(lái)織入Spring AOP。
- Spring只支持方法級(jí)別的連接點(diǎn)。
Spring 使用AspectJ的切點(diǎn)表達(dá)式來(lái)定義切面:
| AspectJ 指示器 | 描述 |
| arg () | 限制連接點(diǎn)的指定參數(shù)為指定類型的執(zhí)行方法 |
| @args () | 限制連接點(diǎn)匹配參數(shù)由指定注解標(biāo)注的執(zhí)行方法 |
| execution () | 用于匹配連接點(diǎn)的執(zhí)行方法 |
| this () | 限制連接點(diǎn)匹配 AOP 代理的 Bean 引用為指定類型的類 |
| target () | 限制連接點(diǎn)匹配特定的執(zhí)行對(duì)象,這些對(duì)象對(duì)應(yīng)的類要具備指定類型注解 |
| within() | 限制連接點(diǎn)匹配指定類型 |
| @within() | 限制連接點(diǎn)匹配指定注釋所標(biāo)注的類型(當(dāng)使用 Spring AOP 時(shí),方法定義在由指定的注解所標(biāo)注的類里) |
| @annotation | 限制匹配帶有指定注釋的連接點(diǎn) |
1. 創(chuàng)建自己的切點(diǎn)?
?
- execution( ) 指示器選擇 Instrument 的 play( ) 方法。?
方法表達(dá)式是以 * 號(hào)開頭,標(biāo)識(shí)了我們不關(guān)心的方法返回值的類型。?
* 后我們指定了權(quán)限定類名和方法名。?
對(duì)于方法的參數(shù)列表,使用(..)標(biāo)識(shí)切點(diǎn)選擇任意的 play( ) 方法,無(wú)論入?yún)⑹鞘裁础?
- 假設(shè)我們需要匹配切點(diǎn)僅匹配 com.Springinaction.springidol 包。可以使用 within()?
?
注意 && 是將 execution( ) 和 within( ) 連接起來(lái),形成的 and 關(guān)系。同理也可以使用 || 或關(guān)系、!非關(guān)系?
- 創(chuàng)建?spring?的 bean( ) 指示器?
Spring 2.5 引入一個(gè)新的 bean( ) 指示器,該指示器允許我們?cè)谇悬c(diǎn)表達(dá)式中使用 Bean ID 來(lái)標(biāo)識(shí) Bean?
bean( ) 使用 Bean ID 或 Bean 名稱作為參數(shù)來(lái)限制切點(diǎn)只匹配特定 Bean。?
如下,我們希望執(zhí)行 Instrument 的 play( ) 方法時(shí)候應(yīng)用通知,但限定 Bean 的 ID 為 eddie?
?
還可以使用非操作作為除了指定 ID 的 Bean 以外的其他 Bean應(yīng)用通知?
?
在此場(chǎng)景下,切面會(huì)通知被編織到所有 ID 不為 eddie 的 Bean 中
?
轉(zhuǎn)載于:https://www.cnblogs.com/xiaolang8762400/p/7020525.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Spring AOP 面向切面编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring Security 入门(1
- 下一篇: OAuth2.0学习(2-1)Sprin