成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring 事務 @Transactional注解 面試及原理

開發 前端
我們都是把注解加到需要使用事務控制的方法上,也可以加到類上,加到類上是給類里的所有的方法都加了事務,不建議這樣做,這樣會增加不需要使用事務的接口的響應時長。

1. 你在項目中是如何使用事物的?

我們項目的框架都是使用的Spring,spring分為 編程式事務,在代碼中硬編碼。聲明式事務,在配置文件中配置(推薦使用)

聲明式事務又分為兩種:基于XML的聲明式事務基于注解的聲明式事務。我一般都是通過注解來進行的事務控制。也就是@Transactional

2. 先簡單介紹一下@Transactional注解嗎?項目中如何使用的?有哪些注意點嗎?

我們都是把注解加到需要使用事務控制的方法上,也可以加到類上,加到類上是給類里的所有的方法都加了事務,不建議這樣做,這樣會增加不需要使用事務的接口的響應時長。

@Transactional注解只能用在public 方法上,如果用在protected或者private的方法上,不會報錯,但是該注解不會生效。

@Transactional注解只能回滾非檢查型異常,具體為RuntimeException及其子類。

3. Spring 事務中的隔離級別有哪幾種?

TransactionDefinition 接口中定義了五個表示隔離級別的常量:

TransactionDefinition.ISOLATION_DEFAULT: 使用后端數據庫默認的隔離級別,

Mysql 默認采用的 REPEATABLE_READ隔離級別 Oracle 默認采用的 READ_COMMITTED隔離級別。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級別,允許讀取未提交的數據變更,可能會導致臟讀、幻讀或不可重復讀。

TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取并發事務已經提交的數據,可以阻止臟讀,但是幻讀或不可重復讀仍有可能發生。

TransactionDefinition.ISOLATION_REPEATABLE_READ: 對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發生。

TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

4. Spring 事務中哪幾種事務傳播行為?

支持當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRED: 如果當前存在事務,則加入該事務;

如果當前沒有事務,則創建一個新的事務。

TransactionDefinition.PROPAGATION_SUPPORTS: 如果當前存在事務,則加入該事務;

如果當前沒有事務,則以非事務的方式繼續運行。

TransactionDefinition.PROPAGATION_MANDATORY: 如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。(mandatory:強制性)不支持當前事務的情況:

不支持當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 創建一個新的事務,

如果當前存在事務,則把當前事務掛起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務方式運行,

如果當前存在事務,則把當前事務掛起。

TransactionDefinition.PROPAGATION_NEVER: 以非事務方式運行,

如果當前存在事務,則拋出異常。

其他情況:

TransactionDefinition.PROPAGATION_NESTED: 如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。

5. @Transactional注解只能用在public 方法上,這是為什么?

Spring事務的實現都是依靠AOP,本質上也是依靠代理來實現。事務在spring中的實現其實就是生成bean對象的代理對象。

在bean進行創建出實例時, 如果是有事務注解的方法,就會被進行增強,最終形成代理類。在spring中,有兩種動態代理的方式,一種是jdk,它是將原始對象放入代理對象內部,通過調用內含的原始對象來實現原始的業務邏輯,而另一種是cglib,它是通過生成原始對象的子類,子類復寫父類的方法,從而實現對父類的增強。

jdk中,如果是private的方法,顯然是無法訪問的,而在cglib中,也是同樣。所以總結來說private方法不能被繼承,final方法不能被重寫,static方法和繼承不相干,所以它們3個的事務不起作用。

Spring選擇讓protected方法和package方法不支持事務,所以只有public方法支持事務

6. 一個類中沒加事務的方法調用加事務的方法,為什么事務失效?怎么解決Spring事務失效的問題?

原因:

Spring事務管理用的是AOP,AOP底層用的是動態代理。所以spring 在掃描bean的時候會掃描方法上是否包含@Transactional注解,如果包含,spring會為這個bean動態地生成一個子類(即代理類,proxy),當這個有注解的方法被調用的時候,實際上是由代理類來調用的,代理類在調用之前就會啟動transaction。然而,如果這個有注解的方法是被同一個類中的其他方法調用的,那么該方法的調用并沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動transaction。

解決方式:

  • 把方法B抽離到另外一個XXService中去,并且在這個Service中注入XXService,使用XXService調用方法B;
  • 通過在方法內部獲得當前類代理對象的方式,通過代理對象調用方法B

上面說了:動態代理最終都是要調用原始對象的,而原始對象在去調用方法時,是不會再觸發代理了!所以我們就使用代理對象來調用,就會觸發事務;

綜上解決方案,那怎么獲取代理對象呢? 這里提供兩種方式:

  • 使用 ApplicationContext 上下文對象獲取該對象;
  • 使用 AopContext.currentProxy() 獲取代理對象,但是需要配置exposeProxy=true

7. 同一個類中標有@Transactional 的方法A,調用另一個標有@Transactional的 方法B會開啟幾個事務?

一個事務

Spring事務管理用的是AOP,AOP底層用的是動態代理。所以spring 在掃描bean的時候會掃描方法上是否包含@Transactional注解,如果包含,spring會為這個bean動態地生成一個子類(即代理類,proxy),代理類是繼承原來那個bean的。

此時,當這個有注解的方法被調用的時候,實際上是由代理類來調用的,代理類在調用之前就會啟動transaction。如果是被同一個類中的其他方法調用的,那么該方法的調用并沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動transaction,我們說只有一個事務。

8. 那么如何才能讓上面兩個方法開啟兩個事務呢?

1.把方法B抽離到另外一個XXService中去,在這個Service中注入XXService,使用XXService調用方法B;

2.通過在方法內部獲得當前類代理對象的方式,通過代理對象調用方法B

上面說了:動態代理最終都是要調用原始對象的,而原始對象在去調用方法時,是不會再觸發代理了!所以我們就使用代理對象來調用,就會觸發事務;

綜上解決方案,那怎么獲取代理對象呢? 這里提供兩種方式:

1.使用 ApplicationContext 上下文對象獲取該對象;

2.使用 AopContext.currentProxy() 獲取代理對象,但是需要配置exposeProxy=true

TestService testService = (TestService)AopContext.currentProxy();

testService.B();

同時還需要在B方法將傳播行為配置為 @Transactional(propagation = Propagation.REQUIRES_NEW)

9. @Transactional實現原理

注解介紹

@Transactional是spring中聲明式事務管理的注解配置方式。@Transactional注解可以幫助我們把事務開啟、提交或者回滾的操作,通過aop的方式進行管理。

通過@Transactional注解就能讓spring為我們管理事務,免去了重復的事務管理邏輯,減少對業務代碼的侵入,使我們開發人員能夠專注于業務層面開發。

我們知道實現@Transactional原理是基于spring aop,aop又是動態代理模式的實現,下面我們就詳細分析一下實現原理

實現原理

猜想

  • 首先,對于spring中aop實現原理有了解的話,應該知道想要對一個方法進行代理的話,肯定需要定義切點。在@Transactional的實現中,同樣如此,spring為我們定義了以 @Transactional 注解為植入點的切點,這樣才能知道@Transactional注解標注的方法需要被代理。
  • 有了切面定義之后,在spring的bean的初始化過程中,就需要對實例化的bean進行代理,并且生成代理對象。
  • 生成代理對象的代理邏輯中,進行方法調用時,需要先獲取切面邏輯,@Transactional注解的切面邏輯類似于@Around,在spring中是實現一種類似代理邏輯。

源碼分析

  • 在配置好注解驅動方式的事務管理之后,spring會在ioc容器創建一個BeanFactoryTransactionAttributeSourceAdvisor實例,這個實例可以看作是一個切點,在判斷一個bean在初始化過程中是否需要創建代理對象,都需要驗證一次BeanFactoryTransactionAttributeSourceAdvisor是否是適用這個bean的切點。如果是,就需要創建代理對象,并且把BeanFactoryTransactionAttributeSourceAdvisor實例注入到代理對象中。
  • 分析代理的對象發現,最終的代理對象的代理方法是DynamicAdvisedInterceptor#intercept,分析這個方法后發現他最終調用的是TransactionInterceptor#invoke方法,并且把CglibMethodInvocation注入到invoke方法中,從上面可以看到CglibMethodInvocation是包裝了目標對象的方法調用的所有必須信息,因此,在TransactionInterceptor#invoke里面也是可以調用目標方法的,并且還可以實現類似@Around的邏輯,在目標方法調用前后繼續注入一些其他邏輯,比如事務管理邏輯。
  • 當我們調進去TransactionInterceptor#invoke方法發現其中的核心方法是invokeWithinTransaction。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-06-26 14:59:13

SpringTransaction執行

2023-11-02 07:52:30

Java工具

2023-09-27 16:22:51

SpringMySQL原子性

2021-04-14 15:17:08

Transaction代碼語言

2023-09-28 09:07:54

注解失效場景

2025-01-16 08:45:48

2022-09-20 22:27:08

事務失效public 修飾

2022-09-14 19:50:22

事務場景流程

2023-04-02 13:57:04

Java自定義事務管理器

2022-08-08 17:38:45

Spring策略事務

2025-01-06 09:26:49

2022-08-09 09:34:32

Spring開發

2023-08-31 08:12:23

應用場景業務異常HTTP

2021-03-10 10:55:51

SpringJava代碼

2020-11-17 08:28:55

數據庫

2021-11-29 06:57:50

并行Stream Spring

2022-02-14 16:53:57

Spring項目數據庫

2018-11-16 15:35:10

Spring事務Java

2020-10-19 11:05:17

SpringTransaction事務

2020-08-19 09:45:29

Spring數據庫代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人综合一区二区三区 | 中文字幕日韩欧美一区二区三区 | 欧美在线综合 | 欧美精品片 | 福利精品| 欧美精品网站 | 国产成人一区二区三区电影 | 麻豆精品一区二区三区在线观看 | 国产精品毛片 | 国产一区二区免费在线 | 久久高潮 | 欧美综合一区 | www国产成人免费观看视频 | 国产高清在线精品 | 天堂成人国产精品一区 | 一级亚洲| 久久综合伊人一区二区三 | 在线观看国产视频 | 在线视频日韩 | www.47久久青青 | 日本天堂视频在线观看 | 日本一区二区三区在线观看 | 国产黄色av电影 | 日韩av免费在线观看 | 国产日韩欧美一区 | 天天射夜夜操 | 天天弄| 二区高清| 九一视频在线观看 | 亚洲免费视频一区二区 | 麻豆精品国产91久久久久久 | 伦理午夜电影免费观看 | 国产人成精品一区二区三 | 欧美一区二区三区在线免费观看 | 国产日韩欧美一区二区 | 国产精品无码专区在线观看 | 日一区二区 | 成人精品国产一区二区4080 | 成人性生交大片 | www.888www看片 | 久久精品久久综合 |