排坑之旅——動態代理給Spring事務種下的坑

前言

Spring的聲明式事務讓咱們不在編寫得到鏈接、關閉鏈接、開啓事務、提交事務、回滾事務等代碼,經過一個簡單的@Transactional註解,就讓咱們輕鬆進行事務處理。咱們知道Spring事務基於AOP,採用動態代理實現,雖然使用簡單,可是在實際場景中,咱們也會遇到一些坑。而每每遇到坑以後,咱們都會茫然,這是因爲沒有對Spring事務的實現機制作一點了解致使的。所以本篇博客將從原理的角度分析下動態代理給Spring事務埋下的坑!sql


從動態代理到Spring事務

UserService:架構

UserService接口

txMethod和txMethod2方法模擬事務方法(至關於@Transactional)併發

noTxMethod方法是普通方法分佈式

UserServiceImpl:高併發

UserServiceImpl

在Spring事務中,咱們每每是在Service層進行事務控制。性能

咱們在UserServiceImpl中想模擬的是:學習

一個有事務的方法,去調用另外一個有事務的方法,會怎麼樣?3d

一個沒有事務的方法,去調用一個有事務的方法,會怎麼樣?代理

UserHandler:orm

UserHandler

這裏爲了簡便,經過方法名稱來判斷是否開啓事務。

顯然,txMethod方法、txMethod2方法都「應該」開啓事務。

UserTest:

UserTest

下面,咱們來講下運行結果:

proxyInstance.txMethod2()方法,會開啓事務,這沒有問題。

proxyInstance.txMethod()方法,雖然在事務方法txMethod()內部調用了txMethod2()事務方法,可是並無新開啓事務。

proxyInstance.noTxMethod()方法,雖然在沒有事務的方法noTxMethod()內部調用了有事務的txMethod2()方法,可是並無開啓事務。

下面讓咱們來對應下Spring事務中的現象:

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等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索