日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

就同一個Service類中,一個事務方法調用另外一個有事務的方法

作者:慕白Lee 更新時間: 2023-09-18 編程語言

目錄

一、Spring 事務機制

二、Spring事務傳播行為

三、場景總結

1、在同一個類中,一個方法調用另外一個有注解(比如@Async,@Transational)的方法,注解是不會生效的

2、在一個Service內部,事務方法之間的嵌套調用,普通方法和事務方法之間的嵌套調用,都不會開啟新的事務.

3、場景總結

4、解決方法

5、使用AOP?代理后的方法調用執行流程

一、Spring 事務機制

Spring對事務控制的支持統一在TransactionDefinition類中描述,該類有以下幾個重要的接口方法:

    int getPropagationBehavior():事務的傳播行為
    int getIsolationLevel():事務的隔離級別
    int getTimeout():事務的過期時間
    boolean isReadOnly():事務的讀寫特性

除了事務的傳播行為外,事務的其他特性Spring是借助底層資源的功能來完成的,Spring無非只充當個代理的角色。但是事務的傳播行為卻是Spring憑借自身的框架提供的功能

二、Spring事務傳播行為

所謂事務傳播行為就是多個事務方法相互調用時,事務如何在這些方法間傳播。Spring支持以下7種事務傳播行為\

Spring事務傳播屬性:
1.propagation-required: 支持當前事務,如果有就加入當前事務中;如果當前方法沒有事務,就新建一個事務;
2.propagation-supports: 支持當前事務,如果有就加入當前事務中;如果當前方法沒有事務,就以非事務的方式執行;
3.propagation-mandatory: 支持當前事務,如果有就加入當前事務中;如果當前沒有事務,就拋出異常;
4.propagation-requires_new: 新建事務,如果當前存在事務,就把當前事務掛起;如果當前方法沒有事務,就新建事務;
5.propagation-not-supported: 以非事務方式執行,如果當前方法存在事務就掛起當前事務;如果當前方法不存在事務,就以非事務方式執行;
6.propagation-never: 以非事務方式執行,如果當前方法存在事務就拋出異常;如果當前方法不存在事務,就以非事務方式執行;
7.propagation-nested: 如果當前方法有事務,則在嵌套事務內執行;如果當前方法沒有事務,則與required操作類似;
前六個策略類似于EJB CMT,第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量。
它要求事務管理器或者使用JDBC 3.0 Savepoint API提供嵌套事務行為(如Spring的DataSourceTransactionManager)
B.b()的事務配置 a()沒有事務的結果 a()有事務的結果
REQUIRED b()創建自己的事務; b()接受a()的事務
SUPPORTS b()不創建自己的事務; b()接受a()的事務
A.a() MANDATORY b()報異常 b()接受a()的事務
NESTED b()創建自己的事務; b()接受a()的事務,成為a()嵌套的子事務
NEVER b()不創建自己的事務; b()報異常
REQUIRES_NEW b()創建自己的事務; b()不接受a()的事務,b()先執行,內層事務失敗不會影響外層事務
NOT_SUPPORTED b()不創建自己的事務; b()不接受a()的事務,b()先執行

三、場景總結

1在同一個類中,一個方法調用另外一個有注解(比如@Async,@Transational)的方法,注解是不會生效的

有兩方法,一個有@Transational注解,一個沒有。如果調用了有注解的A()方法,會啟動一個Transaction;如果調用B(),因為它內部調用了有注解的A(),但實際上它不會啟動一個Transaction的

@Service
public class DemoServiceImpl implements DemoService {
 
 @Autowired
 DemoDao demoDao;
 
 @Override
 @Transactional
 public boolean A(Demo demo) {
  log.info("sbplus");
 }
 

//測試同一個類中@Transactional是否起作用
 @Override
 //@Transactional
 public void B(Demo demo) {
  A(demo); 
 }
}

原因

????????spring 在掃描bean的時候會掃描方法上是否包含@Transactional注解,如果包含,spring會為這個bean動態地生成一個子類(即代理類,proxy),代理類是繼承原來那個bean的。此時,當這個有注解的方法被調用的時候,實際上是由代理類來調用的,代理類在調用之前就會啟動transaction。然而,如果這個有注解的方法是被同一個類中的其他方法調用的,那么該方法的調用并沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動transaction,我們看到的現象就是@Transactional注解無效。

為什么一個方法a()調用同一個類中另外一個方法b()的時候,b()不是通過代理類來調用的呢?可以看下面的例子:

@Service
class A{
    @Transactinal
    method b(){...}
    
    method a(){    //標記1
        b();
    }
}
 
//Spring掃描注解后,創建了另外一個代理類,并為有注解的方法插入一個startTransaction()方法:
class proxy$A{
    A objectA = new A();
    method b(){    //標記2
        startTransaction();
        objectA.b();
    }
 
    method a(){    //標記3
        objectA.a();    //由于a()沒有注解,所以不會啟動transaction,而是直接調用A的實例的a()方法
    }
}

當我們調用A的bean的a()方法的時候,也是被proxy$A攔截,執行proxy$A.a()(標記3),然而,由以上代碼可知,這時候它調用的是objectA.a(),也就是由原來的bean來調用a()方法了,所以代碼跑到了“標記1”。由此可見,“標記2”并沒有被執行到,所以startTransaction()方法也沒有運行。

2、在一個Service內部,事務方法之間的嵌套調用,普通方法和事務方法之間的嵌套調用,都不會開啟新的事務.

A方法(無事務)調B方法(有事務)事務是不生效。

1)、spring采用動態代理機制來實現事務控制,而動態代理最終都是要調用原始對象的,而原始對象在去調用方法時,是不會再觸發代理了!

2)、Spring的事務管理是通過AOP實現的,其AOP的實現對于非final類是通過cglib這種方式,即生成當前類的一個子類作為代理類,然后在調用其下的方法時,會判斷這個方法有沒有@Transactional注解,如果有的話,則通過動態代理實現事務管理(攔截方法調用,執行事務等切面)。當b()中調用a()時,發現b()上并沒有@Transactional注解,所以整個AOP代理過程(事務管理)不會發生。

3、場景總結

4、解決方法

重新建一個service類來寫B方法。

5、使用AOP?代理后的方法調用執行流程

?

?

有用請點贊,養成良好習慣!

疑問、交流、鼓勵請留言!


原文鏈接:https://libusi.blog.csdn.net/article/details/127355073

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新