Spring AOP高級(jí)應(yīng)用與源碼剖析
Spring AOP 高級(jí)應(yīng)用
AOP的本質(zhì):在不改變?cè)袠I(yè)務(wù)邏輯的情況下增強(qiáng)橫切邏輯,橫切邏輯代碼往往是權(quán)限校驗(yàn)代碼,日志代碼,事務(wù)控制代碼,性能監(jiān)測(cè)代碼。
AOP相關(guān)術(shù)語(yǔ)
名詞 | 解釋 |
JoinPoint(連接點(diǎn)) | 可以用于把增強(qiáng)代碼加入到業(yè)務(wù)主線中的點(diǎn) |
Pointcut(切入點(diǎn)) | 已經(jīng)把增強(qiáng)代碼加入到業(yè)務(wù)主線進(jìn)來(lái)之后的連接點(diǎn) |
Adice(通知/增強(qiáng)) | 切面類中用于提供增強(qiáng)功能的方法 |
Target(目標(biāo)對(duì)象) | 代理的目標(biāo)對(duì)象。即被代理對(duì)象 |
Proxy(代理) | 一個(gè)類被AOP植入增強(qiáng)后,產(chǎn)生的代理類 |
Weaving(織入) | 把增強(qiáng)應(yīng)用到目標(biāo)對(duì)象來(lái)創(chuàng)建新的代理對(duì)象的過(guò)程 |
Aspect(切面) | 指定增強(qiáng)的代碼所關(guān)注的方面,把這些相關(guān)的增強(qiáng)代碼定義到一個(gè)類中,這個(gè)類就是切面類。 |
Spring中AOP的代理選擇
AOP思想使用的是動(dòng)態(tài)代理。默認(rèn)情況下Spring會(huì)根據(jù)代理對(duì)象是否實(shí)現(xiàn)接口來(lái)選擇使用JDK還是CGLIB。當(dāng)代理對(duì)象沒(méi)有實(shí)現(xiàn)任何接口時(shí),Spring會(huì)選擇CGLIB。
Spring中AOP實(shí)現(xiàn)XML形式
maven坐標(biāo)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>Aop核心配置
<!-- Spring基于XML的AOP配置前期準(zhǔn)備: 在spring的配置?件中加?aop的約束 xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd Spring基于XML的AOP配置步驟、 第?步:把通知Bean交給Spring管理 第?步:使?aop:config開始aop的配置 第三步:使?aop:aspect配置切? 第四步:使?對(duì)應(yīng)的標(biāo)簽配置通知的類型 ??案例采?前置通知,標(biāo)簽為aop:before --> <!--把通知bean交給spring來(lái)管理--> <bean id="logUtil" class="com.lagou.utils.LogUtil"></bean> <!--開始aop的配置--> <aop:config> <!--配置切?--> <aop:aspect id="logAdvice" ref="logUtil"> <!--配置前置通知--> <aop:before method="printLog" pointcut="execution(public * com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou .pojo.Account))"></aop:before> </aop:aspect> </aop:config>
切入表達(dá)式,也稱之為Aspectj切入點(diǎn)表達(dá)式,指的是遵循特定語(yǔ)法結(jié)構(gòu)的字符串,其作用是用于對(duì)符合語(yǔ)法格式的連接點(diǎn)進(jìn)行增強(qiáng)。
改變代理方式的配置:
我們知道只要不是final修飾的類都可以是cglib提供的方式來(lái)創(chuàng)建代理對(duì)象,spring提供了兩種配置方式:
- 使用aop:config標(biāo)簽配置
<aop:config proxy-target-class="true">
- 使用aop:aspectj-autoproxy標(biāo)簽配置
<!--此標(biāo)簽是基于XML和注解組合配置AOP時(shí)的必備標(biāo)簽,表示Spring開啟注解配置AOP的?持--> <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectjautoproxy>
5中AOP通知類型:
1. 前置通知
- 配置方式:
<aop:before method="方法名" pointcut-ref="切入點(diǎn)引用"/> - 出現(xiàn)位置:僅在
<aop:aspect>標(biāo)簽內(nèi) - 執(zhí)行時(shí)機(jī):切入方法(業(yè)務(wù)核心方法)執(zhí)行之前(必定執(zhí)行)
- 細(xì)節(jié):可獲取切入方法的參數(shù)并增強(qiáng)
2. 正常執(zhí)行時(shí)通知(后置返回通知)
- 配置方式:
<aop:after-returning method="方法名" pointcut-ref="切入點(diǎn)引用"/> - 出現(xiàn)位置:僅在
<aop:aspect>標(biāo)簽內(nèi) - 執(zhí)行時(shí)機(jī):切入方法正常執(zhí)行完成后(若方法拋異常則不執(zhí)行)
3. 異常通知
- 配置方式:
<aop:after-throwing method="方法名" pointcut-ref="切入點(diǎn)引用"/> - 出現(xiàn)位置:僅在
<aop:aspect>標(biāo)簽內(nèi) - 執(zhí)行時(shí)機(jī):切入方法產(chǎn)生異常之后(無(wú)異常則不執(zhí)行)
- 細(xì)節(jié):可獲取切入方法的參數(shù) + 異常信息
4. 最終通知
- 配置方式:
<aop:after method="方法名" pointcut-ref="切入點(diǎn)引用"/> - 出現(xiàn)位置:僅在
<aop:aspect>標(biāo)簽內(nèi) - 執(zhí)行時(shí)機(jī):切入方法執(zhí)行完成后、返回之前(無(wú)論是否拋異常,必定執(zhí)行)
- 細(xì)節(jié):可獲取參數(shù),常用于清理操作
5. 環(huán)繞通知
- 配置方式:
<aop:around method="方法名" pointcut-ref="切入點(diǎn)引用"/> - 出現(xiàn)位置:僅在
<aop:aspect>標(biāo)簽內(nèi) - 特殊說(shuō)明:是 Spring 的 “特殊通知”,可通過(guò)編程控制通知執(zhí)行時(shí)機(jī)(區(qū)別于前四種 “指定時(shí)機(jī)” 的通知);依賴
ProceedingJoinPoint接口,實(shí)現(xiàn)手動(dòng)觸發(fā)切入方法的調(diào)用
Spring中AOP實(shí)現(xiàn)XML+注解形式
XML配置 | 注解配置 |
<aop:before method="方法名" pointcut-ref="切入點(diǎn)引用"/> | @Before |
<aop:after-returning method="方法名" pointcut-ref="切入點(diǎn)引用"/> | @AfterReturning |
<aop:after-throwing method="方法名" pointcut-ref="切入點(diǎn)引用"/> | @AfterThrowing |
<aop:after method="方法名" pointcut-ref="切入點(diǎn)引用"/> | @After |
<aop:around method="方法名" pointcut-ref="切入點(diǎn)引用"/> | @Around |
Spring中AOP實(shí)現(xiàn)注解形式
在我們使用注解開發(fā)時(shí)候要用注解替換掉配置文件
<!--開啟spring對(duì)注解aop的?持--> <aop:aspectj-autoproxy/>
需要在啟動(dòng)類上面添加
@EnableAspectJAutoProxy //開啟spring對(duì)注解AOP的?持
Spring聲明式事務(wù)的支持
編程式事務(wù):在業(yè)務(wù)代碼中添加事務(wù)控制代碼,這樣的事務(wù)控制機(jī)制叫做編程式事務(wù)。
聲明式事務(wù):通過(guò)xml或者注解配置的方式達(dá)到事務(wù)控制的目的,叫做聲明式事務(wù)。
事務(wù)的四大特性:
- 原子性:原子性式指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么全部發(fā)生,要么全部不發(fā)生。
- 一致性:事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變換成另一個(gè)一致性狀態(tài)。
- 隔離性:事務(wù)的隔離性式多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),數(shù)據(jù)庫(kù)未每一個(gè)用戶開啟的事務(wù),每個(gè)事務(wù)不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
- 持久性:持久性時(shí)指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)中數(shù)據(jù)的改變就是永久性的,接下來(lái)即使數(shù)據(jù)庫(kù)發(fā)送故障也不應(yīng)該對(duì)其有任何影響。
不考慮事務(wù)隔離級(jí)別會(huì)出現(xiàn)的問(wèn)題:
- 臟讀:一個(gè)線程中的事務(wù)讀到另一個(gè)線程中未提交的數(shù)據(jù)。
- 不可重復(fù)讀:一個(gè)線程的事務(wù)讀到另一個(gè)線程中已經(jīng)提交的update的數(shù)據(jù)(前后內(nèi)容不一樣)。
- 幻讀:一個(gè)線程中的事務(wù)讀取到了另一個(gè)線程中已經(jīng)提交的insert或者delete的數(shù)據(jù)(前后條數(shù)不一樣)。
數(shù)據(jù)庫(kù)中定義的四種隔離級(jí)別(從高到低):
- Serializable(串行化):避免臟讀,不可重復(fù)讀,虛讀情況的發(fā)生。
- Repeatable read(可重復(fù)讀):可避免臟讀,不可重復(fù)讀情況發(fā)生。
- Read committed(讀已提交):可避免臟讀情況發(fā)生。
- Read uncommitted(讀未提交):以上情況都沒(méi)有保證。
Mysql默認(rèn)的事務(wù)隔離級(jí)別是:讀已提交。
查詢當(dāng)前使用的隔離級(jí)別:SELECT @@session.transaction_isolation;
設(shè)置Mysql事務(wù)的隔離級(jí)別:(僅僅是當(dāng)前會(huì)話的隔離級(jí)別)SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
傳播行為常量 | 中文名稱 | 核心規(guī)則 | 適用場(chǎng)景 |
(默認(rèn)) | 必需的 | 如果當(dāng)前有事務(wù),加入該事務(wù);如果無(wú)事務(wù),新建事務(wù)。 | 絕大多數(shù)業(yè)務(wù)(如訂單 + 庫(kù)存) |
| 支持的 | 如果當(dāng)前有事務(wù),加入;無(wú)事務(wù),則以非事務(wù)方式執(zhí)行。 | 查詢類方法(可選事務(wù)) |
| 強(qiáng)制的 | 必須在已有事務(wù)中執(zhí)行;無(wú)事務(wù)則拋異常( | 核心子操作(必須依賴外層事務(wù)) |
| 新建的 | 無(wú)論當(dāng)前是否有事務(wù),都新建獨(dú)立事務(wù);原有事務(wù)暫停,新事務(wù)執(zhí)行完后恢復(fù)。 | 日志記錄、消息發(fā)送(獨(dú)立事務(wù)) |
| 不支持的 | 以非事務(wù)方式執(zhí)行;若當(dāng)前有事務(wù),暫停原有事務(wù)。 | 純查詢(無(wú)需事務(wù),提升性能) |
| 從不 | 必須以非事務(wù)方式執(zhí)行;若當(dāng)前有事務(wù),拋異常。 | 絕對(duì)禁止事務(wù)的操作 |
| 嵌套的 | 基于當(dāng)前事務(wù)創(chuàng)建嵌套子事務(wù)(Savepoint 實(shí)現(xiàn));子事務(wù)回滾不影響外層,外層回滾則全滾。 | 批量操作(部分失敗可回滾) |
純xml方式
<!-- 配置事務(wù)管理器(基于JDBC數(shù)據(jù)源) -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/> <!-- 引用已配置的數(shù)據(jù)源 -->
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 全局默認(rèn)配置:所有方法默認(rèn)非只讀,傳播行為REQUIRED -->
<tx:method name="*" read-only="false"
propagation="REQUIRED" isolation="DEFAULT" timeout="-1"/>
<!-- 針對(duì)查詢方法的單獨(dú)配置:只讀,傳播行為SUPPORTS -->
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 切入點(diǎn):匹配TransferServiceImpl類的所有方法 -->
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/>
</aop:config>xml+注解方式
<!-- 開啟Spring注解事務(wù)的支持 --> <tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
純注解方式
需要在啟動(dòng)類上加入@EnableTransactionManagement
到此這篇關(guān)于Spring AOP高級(jí)應(yīng)用與源碼剖析的文章就介紹到這了,更多相關(guān)Spring AOP源碼分析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在IDEA中搭建最小可用SpringMVC項(xiàng)目(純Java配置)
這篇文章主要介紹了在IDEA中搭建最小可用SpringMVC項(xiàng)目(純Java配置),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
SpringCloud整合Activiti過(guò)程中的踩坑記錄
由于項(xiàng)目需要,最近開始在項(xiàng)目Spring boot中集成工作流引擎Activiti,由于第一次集成,一路上步步都是坑,所以這篇文章主要給大家介紹了關(guān)于SpringCloud整合Activiti過(guò)程中所遇到的踩坑記錄,需要的朋友可以參考下2021-09-09
IDEA運(yùn)行導(dǎo)入的javaweb項(xiàng)目tomcat正常,但是運(yùn)行失敗404問(wèn)題
這篇文章主要介紹了IDEA運(yùn)行導(dǎo)入的javaweb項(xiàng)目tomcat正常但是運(yùn)行失敗404問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
xxl-job在 Spring Boot 項(xiàng)目中的完整配置指南(最新整理)
本文詳細(xì)介紹了Spring Boot任務(wù)調(diào)度配置,包括依賴配置、多環(huán)境支持、任務(wù)處理器、高級(jí)配置、常見(jiàn)問(wèn)題及解決方法,以及項(xiàng)目結(jié)構(gòu)和注意事項(xiàng),感興趣的朋友跟隨小編一起看看吧2025-12-12
通過(guò)Spring AOP實(shí)現(xiàn)異常捕捉機(jī)制
在開發(fā)過(guò)程中,異常處理是一個(gè)不可忽視的重要環(huán)節(jié),合理、優(yōu)雅地處理異常不僅能提高代碼的魯棒性,還能提升系統(tǒng)的用戶體驗(yàn),本文將介紹如何通過(guò)Spring AOP實(shí)現(xiàn)一個(gè)高效的異常捕捉機(jī)制,使得異常處理變得更加優(yōu)雅和統(tǒng)一,需要的朋友可以參考下2024-08-08
基于springboot服務(wù)間Feign調(diào)用超時(shí)的解決方案
這篇文章主要介紹了基于springboot服務(wù)間Feign調(diào)用超時(shí)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07

