spring事務失效場景可能大家在很多文章都看過了,所以今天就水壹篇,看大家能不能收獲壹些不壹樣的東西。直接進入主題
失效原因: spring事務生效的前提是,service必須是壹個bean對象
解決方案: 將service註入spring
失效原因: spring默認只會回滾非檢查異常和error異常
解決方案: 配置rollbackFor
失效原因: spring事務只有捕捉到了業務拋出去的異常,才能進行後續的處理,如果業務自己捕獲了異常,則事務無法感知
解決方案:
1、將異常原樣拋出;
2、設置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
失效原因: spring事務切面的優先級順序最低,但如果自定義的切面優先級和他壹樣,且自定義的切面沒有正確處理異常,則會同業務自己捕獲異常的那種場景壹樣
解決方案:
1、在切面中將異常原樣拋出;
2、在切面中設置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
失效原因: spring事務默認生效的方法權限都必須為public
解決方案:
1、將方法改為public;
2、修改TansactionAttributeSource,將publicMethodsOnly改為false這個從源碼跟蹤得出結論
3、開啟 AspectJ 代理模式從spring文檔得出結論
具體步驟:
1、在pom引入aspectjrt坐標以及相應插件
2、在啟動類上加上如下配置
註: 如果是在idea上運行,則需做如下配置
4、直接用TransactionTemplate
示例:
失效原因: 子容器掃描範圍過大,將未加事務配置的serivce掃描進來
解決方案:
1、父子容器個掃個的範圍;
2、不用父子容器,所有bean都交給同壹容器管理
註: 因為示例是使用springboot,而springboot啟動默認沒有父子容器,只有壹個容器,因此就該場景就演示示例了
失效原因: 因為spring事務是用動態代理實現,因此如果方法使用了final修飾,則代理類無法對目標方法進行重寫,植入事務功能
解決方案:
1、方法不要用final修飾
失效原因: 原因和final壹樣
解決方案:
1、方法不要用static修飾
失效原因: 本類方法不經過代理,無法進行增強
解決方案:
1、註入自己來調用;
2、使用@EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy()
失效原因: 因為spring的事務是通過數據庫連接來實現,而數據庫連接spring是放在threadLocal裏面。同壹個事務,只能用同壹個數據庫連接。而多線程場景下,拿到的數據庫連接是不壹樣的,即是屬於不同事務
失效原因: 使用的傳播特性不支持事務
失效原因: 使用了不支持事務的存儲引擎。比如mysql中的MyISAM
註: 因為springboot,他默認已經開啟事務管理器。org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration。因此示例略過
失效原因: 當代理類的實例化早於AbstractAutoProxyCreator後置處理器,就無法被AbstractAutoProxyCreator後置處理器增強
本文列舉了14種spring事務失效的場景,其實這14種裏面有很多都是歸根結底都是屬於同壹類問題引起,比如因為動態代理原因、方法限定符原因、異常類型原因等
/lyb-geek/springboot-learning/tree/master/springboot-transaction-invalid-case