<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何將 @Transactional 事務(wù)注解運用到爐火純青?

          共 3677字,需瀏覽 8分鐘

           ·

          2022-06-21 03:27

          程序員的成長之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享 
          關(guān)注


          閱讀本文大概需要 5 分鐘。

          來自:blog.csdn.net/fanxb92/article/details/81296005

          前兩天在工作中忙的焦頭爛額,涉及到@Transactional對于事務(wù)的控制,便仔細(xì)研究了一下,頗有所獲,花費好了幾天測試整理,今天才發(fā)表出來,希望看到的老鐵們能有所獲吧。話不多說直奔正題。


          # 先簡單介紹一下Spring事務(wù)的傳播行為:


          所謂事務(wù)的傳播行為是指,如果在開始當(dāng)前事務(wù)之前,一個事務(wù)上下文已經(jīng)存在,此時有若干選項可以指定一個事務(wù)性方法的執(zhí)行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:


          • TransactionDefinition.PROPAGATION_REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。這是默認(rèn)值。

          • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

          • TransactionDefinition.PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行。

          • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

          • TransactionDefinition.PROPAGATION_NEVER:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則拋出異常。

          • TransactionDefinition.PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。

          • TransactionDefinition.PROPAGATION_NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行;如果當(dāng)前沒有事務(wù),則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。


          # 然后說一下Spring事務(wù)的回滾機制:


          Spring的AOP即聲明式事務(wù)管理默認(rèn)是針對unchecked exception回滾。Spring的事務(wù)邊界是在調(diào)用業(yè)務(wù)方法之前開始的,業(yè)務(wù)方法執(zhí)行完畢之后來執(zhí)行commit or rollback(Spring默認(rèn)取決于是否拋出runtimeException)。


          如果你在方法中有try{}catch(Exception e){}處理,那么try里面的代碼塊就脫離了事務(wù)的管理,若要事務(wù)生效需要在catch中throw new RuntimeException ("xxxxxx");這一點也是面試中會問到的事務(wù)失效的場景。


          再簡單介紹一下@Transactional注解底層實現(xiàn)方式吧,毫無疑問,是通過動態(tài)代理,那么動態(tài)代理又分為JDK自身和CGLIB,這個也不多贅述了,畢竟今天的主題是如何將@Transactional對于事物的控制應(yīng)用到爐火純青。哈哈~


          第一點要注意的就是在@Transactional注解的方法中,再調(diào)用本類中的其他方法method2時,那么method2方法上的@Transactional注解是不!會!生!效!的!但是加上也并不會報錯,拿圖片簡單幫助理解一下吧。這一點也是面試中會問到的事務(wù)失效的場景。


          通過代理對象在目標(biāo)對象前后進(jìn)行方法增強,也就是事務(wù)的開啟提交和回滾。那么繼續(xù)調(diào)用本類中其他方法是怎樣呢,如下圖:



          可見目標(biāo)對象內(nèi)部的自我調(diào)用,也就是通過this.指向的目標(biāo)對象將不會執(zhí)行方法的增強。

          先說第二點需要注意的地方,等下說如何解決上面第一點的問題。第二點就是@Transactional注解的方法必須是公共方法,就是必須是public修飾符!!!


          至于這個的原因,發(fā)表下個人的理解吧,因為JVM的動態(tài)代理是基于接口實現(xiàn)的,通過代理類將目標(biāo)方法進(jìn)行增強,想一下也是啦,沒有權(quán)限訪問那么你讓我怎么進(jìn)行,,,好吧,這個我也沒有深入研究底層,個人理解個人理解。


          在這里我也放個問題吧,希望有高手可以回復(fù)指點指點我,因為JVM動態(tài)代理是基于接口實現(xiàn)的,那么是不是service層都要按照接口和實現(xiàn)類的開發(fā)模式,注解才會生效呢,就是說controller層直接調(diào)用沒有接口的service層,加了注解也一樣不起作用吧,這個懶了,沒有測試,其一是因為沒有人會這么開發(fā)吧,其二是我就認(rèn)為是不起作用的,哈哈


          下面來解決一下第一點的問題,如何在方法中調(diào)用本類中其他方法呢。


          通過AopContext.currentProxy ()獲取到本類的代理對象,再去調(diào)用就好啦。因為這個是CGLIB實現(xiàn),所以要開啟AOP,當(dāng)然也很簡單,在springboot啟動類上加上注解@EnableAspectJAutoProxy(exposeProxy = true)就可以啦,這個依賴大家自行搜一下就好啦。要注意,注意,代理對象調(diào)用的方法也要是public修飾符,否則方法中獲取不到注入的bean,會報空指針錯誤。


          emmmm,我先把調(diào)用的方式和結(jié)果說下吧。自己簡單寫了代碼,有點粗糙,就不要介意啦,嘿嘿。。。
          Controller中調(diào)用Service
          @RestControllerpublic class TransactionalController { @Autowired private TransactionalService transactionalService; @PostMapping("transactionalTest") public void transacionalTest(){ transactionalService.transactionalMethod(); }}
          Service中實現(xiàn)對事務(wù)的控制:接口
          public interface TransactionalService { void transactionalMethod();}
          Service中實現(xiàn)對事務(wù)的控制:實現(xiàn)類(各種情況的說明都寫在圖片里了,這樣方便閱讀,有助于快速理解吧)



          上面兩種情況不管使不使用代理調(diào)用方法1和方法2,方法transactionalMethod都處在一個事務(wù)中,四條更新操作全部失敗。


          那么有人可能會有疑問了,在方法1和方法2上都加@Transactional注解呢?答案是結(jié)果和上面是一致的。


          小結(jié)只要方法transactionalMethod上有注解,并且方法1和方法2都處于當(dāng)前事務(wù)中(不使用代理調(diào)用,方法1和方法2上的@Transactional注解是不生效的;使用代理,需要方法1和方法2都處在transactionalMethod方法的事務(wù)中,默認(rèn)或者嵌套事務(wù)均可,當(dāng)然也可以不加@Transactional注解),那么整體保持事務(wù)一致性。


          如果想要方法1和方法2均單獨保持事務(wù)一致性怎么辦呢,剛說過了,如果不是用代理調(diào)用@Transactional注解是不生效的,所以一定要使用代理調(diào)用實現(xiàn),然后讓方法1和方法2分別單獨開啟新的事務(wù),便OK啦。下面擺上圖片。



          這兩種情況都是方法1和方法2均處在單獨的事務(wù)中,各自保持事務(wù)的一致性。


          接下來進(jìn)行進(jìn)一步的優(yōu)化,可以在transactionalMethod方法中分別對方法1和方法2進(jìn)行控制。要將代碼的藝術(shù)發(fā)揮到極致嘛,下面裝逼開始。



          代碼太長了,超過屏幕了,粘貼出來截的圖,紅框注釋需要仔細(xì)看,希望不要影響你的閱讀體驗,至此,本篇關(guān)于@Transactioinal注解的使用就到此為止啦,


          簡單總結(jié)一下吧:


          1、就是@Transactional注解保證的是每個方法處在一個事務(wù),如果有try一定在catch中拋出運行時異常。


          2、方法必須是public修飾符。否則注解不會生效,但是加了注解也沒啥毛病,不會報錯,只是沒卵用而已。


          3、this.本方法的調(diào)用,被調(diào)用方法上注解是不生效的,因為無法再次進(jìn)行切面增強。


          如果有更細(xì)致的討論歡迎評論,感謝閱讀。
          <END>

          推薦閱讀:

          一段很有意思的代碼!!

          100 行代碼搞定了 RPC 原理,大家隨便問!

          互聯(lián)網(wǎng)初中高級大廠面試題(9個G)

          內(nèi)容包含Java基礎(chǔ)、JavaWeb、MySQL性能優(yōu)化、JVM、鎖、百萬并發(fā)、消息隊列、高性能緩存、反射、Spring全家桶原理、微服務(wù)、Zookeeper......等技術(shù)棧!

          ?戳閱讀原文領(lǐng)取!                                  朕已閱 

          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国一级毛片视频 | 瘦精品无码一区二区三区四区五区六区七区八区 | 精品人妻一区二区免费蜜桃视频 | 青娱乐亚洲视频在线 | 91亚洲欧美福利在线观看 |