Spring的聲明式事務讓咱們不在編寫得到鏈接、關閉鏈接、開啓事務、提交事務、回滾事務等代碼,經過一個簡單的@Transactional註解,就讓咱們輕鬆進行事務處理。咱們知道Spring事務基於AOP,採用動態代理實現,雖然使用簡單,可是在實際場景中,咱們也會遇到一些坑。而每每遇到坑以後,咱們都會茫然,這是因爲沒有對Spring事務的實現機制作一點了解致使的。所以本篇博客將從原理的角度分析下動態代理給Spring事務埋下的坑!sql
UserService:架構
txMethod和txMethod2方法模擬事務方法(至關於@Transactional)併發
noTxMethod方法是普通方法分佈式
UserServiceImpl:高併發
在Spring事務中,咱們每每是在Service層進行事務控制。性能
咱們在UserServiceImpl中想模擬的是:學習
一個有事務的方法,去調用另外一個有事務的方法,會怎麼樣?3d
一個沒有事務的方法,去調用一個有事務的方法,會怎麼樣?代理
UserHandler:orm
這裏爲了簡便,經過方法名稱來判斷是否開啓事務。
顯然,txMethod方法、txMethod2方法都「應該」開啓事務。
UserTest:
下面,咱們來講下運行結果:
proxyInstance.txMethod2()方法,會開啓事務,這沒有問題。
proxyInstance.txMethod()方法,雖然在事務方法txMethod()內部調用了txMethod2()事務方法,可是並無新開啓事務。
proxyInstance.noTxMethod()方法,雖然在沒有事務的方法noTxMethod()內部調用了有事務的txMethod2()方法,可是並無開啓事務。
下面讓咱們來對應下Spring事務中的現象:
上述的狀況,說白了,就是在一個Service內部,事務方法之間的嵌套調用,普通方法和事務方法之間的嵌套調用,都不會開啓新的事務!
爲何會這樣呢?
其實經過上面的動態代理的代碼,你應該能夠發現:
動態代理最終都是要調用原始對象的,而原始對象在去調用方法時,是不會再觸發代理了!
那麼如何解決呢?
很簡單,咱們徹底能夠在抽出一個XxxService,在其內部調用UserService.txMethod()和UserService.txMethod2()方法便可。總而言之,避免在一個Service內部進行事務方法的嵌套調用!(由於動態代理致使這種場景事務失效了。)
好像Spring事務如此簡單,可是背後卻有這些道道,你被坑過麼?
歡迎工做一到五年的Java工程師朋友們加入Java架構開發:878249276
羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!