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

Spring 事務(wù) @Transactional注解 面試及原理

開(kāi)發(fā) 前端
我們都是把注解加到需要使用事務(wù)控制的方法上,也可以加到類上,加到類上是給類里的所有的方法都加了事務(wù),不建議這樣做,這樣會(huì)增加不需要使用事務(wù)的接口的響應(yīng)時(shí)長(zhǎng)。

1. 你在項(xiàng)目中是如何使用事物的?

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

聲明式事務(wù)又分為兩種:基于XML的聲明式事務(wù)基于注解的聲明式事務(wù)。我一般都是通過(guò)注解來(lái)進(jìn)行的事務(wù)控制。也就是@Transactional

2. 先簡(jiǎn)單介紹一下@Transactional注解嗎?項(xiàng)目中如何使用的?有哪些注意點(diǎn)嗎?

我們都是把注解加到需要使用事務(wù)控制的方法上,也可以加到類上,加到類上是給類里的所有的方法都加了事務(wù),不建議這樣做,這樣會(huì)增加不需要使用事務(wù)的接口的響應(yīng)時(shí)長(zhǎng)。

@Transactional注解只能用在public 方法上,如果用在protected或者private的方法上,不會(huì)報(bào)錯(cuò),但是該注解不會(huì)生效。

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

3. Spring 事務(wù)中的隔離級(jí)別有哪幾種?

TransactionDefinition 接口中定義了五個(gè)表示隔離級(jí)別的常量:

TransactionDefinition.ISOLATION_DEFAULT: 使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別,

Mysql 默認(rèn)采用的 REPEATABLE_READ隔離級(jí)別 Oracle 默認(rèn)采用的 READ_COMMITTED隔離級(jí)別。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級(jí)別,允許讀取未提交的數(shù)據(jù)變更,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀。

TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生。

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

TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級(jí)別,完全服從ACID的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說(shuō),該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別。

4. Spring 事務(wù)中哪幾種事務(wù)傳播行為?

支持當(dāng)前事務(wù)的情況:

TransactionDefinition.PROPAGATION_REQUIRED: 如果當(dāng)前存在事務(wù),則加入該事務(wù);

如果當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。

TransactionDefinition.PROPAGATION_SUPPORTS: 如果當(dāng)前存在事務(wù),則加入該事務(wù);

如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。

TransactionDefinition.PROPAGATION_MANDATORY: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則拋出異常。(mandatory:強(qiáng)制性)不支持當(dāng)前事務(wù)的情況:

不支持當(dāng)前事務(wù)的情況:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 創(chuàng)建一個(gè)新的事務(wù),

如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務(wù)方式運(yùn)行,

如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

TransactionDefinition.PROPAGATION_NEVER: 以非事務(wù)方式運(yùn)行,

如果當(dāng)前存在事務(wù),則拋出異常。

其他情況:

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

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

Spring事務(wù)的實(shí)現(xiàn)都是依靠AOP,本質(zhì)上也是依靠代理來(lái)實(shí)現(xiàn)。事務(wù)在spring中的實(shí)現(xiàn)其實(shí)就是生成bean對(duì)象的代理對(duì)象。

在bean進(jìn)行創(chuàng)建出實(shí)例時(shí), 如果是有事務(wù)注解的方法,就會(huì)被進(jìn)行增強(qiáng),最終形成代理類。在spring中,有兩種動(dòng)態(tài)代理的方式,一種是jdk,它是將原始對(duì)象放入代理對(duì)象內(nèi)部,通過(guò)調(diào)用內(nèi)含的原始對(duì)象來(lái)實(shí)現(xiàn)原始的業(yè)務(wù)邏輯,而另一種是cglib,它是通過(guò)生成原始對(duì)象的子類,子類復(fù)寫(xiě)父類的方法,從而實(shí)現(xiàn)對(duì)父類的增強(qiáng)。

jdk中,如果是private的方法,顯然是無(wú)法訪問(wèn)的,而在cglib中,也是同樣。所以總結(jié)來(lái)說(shuō)private方法不能被繼承,final方法不能被重寫(xiě),static方法和繼承不相干,所以它們3個(gè)的事務(wù)不起作用。

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

6. 一個(gè)類中沒(méi)加事務(wù)的方法調(diào)用加事務(wù)的方法,為什么事務(wù)失效?怎么解決Spring事務(wù)失效的問(wèn)題?

原因:

Spring事務(wù)管理用的是AOP,AOP底層用的是動(dòng)態(tài)代理。所以spring 在掃描bean的時(shí)候會(huì)掃描方法上是否包含@Transactional注解,如果包含,spring會(huì)為這個(gè)bean動(dòng)態(tài)地生成一個(gè)子類(即代理類,proxy),當(dāng)這個(gè)有注解的方法被調(diào)用的時(shí)候,實(shí)際上是由代理類來(lái)調(diào)用的,代理類在調(diào)用之前就會(huì)啟動(dòng)transaction。然而,如果這個(gè)有注解的方法是被同一個(gè)類中的其他方法調(diào)用的,那么該方法的調(diào)用并沒(méi)有通過(guò)代理類,而是直接通過(guò)原來(lái)的那個(gè)bean,所以就不會(huì)啟動(dòng)transaction。

解決方式:

  • 把方法B抽離到另外一個(gè)XXService中去,并且在這個(gè)Service中注入XXService,使用XXService調(diào)用方法B;
  • 通過(guò)在方法內(nèi)部獲得當(dāng)前類代理對(duì)象的方式,通過(guò)代理對(duì)象調(diào)用方法B

上面說(shuō)了:動(dòng)態(tài)代理最終都是要調(diào)用原始對(duì)象的,而原始對(duì)象在去調(diào)用方法時(shí),是不會(huì)再觸發(fā)代理了!所以我們就使用代理對(duì)象來(lái)調(diào)用,就會(huì)觸發(fā)事務(wù);

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

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

7. 同一個(gè)類中標(biāo)有@Transactional 的方法A,調(diào)用另一個(gè)標(biāo)有@Transactional的 方法B會(huì)開(kāi)啟幾個(gè)事務(wù)?

一個(gè)事務(wù)

Spring事務(wù)管理用的是AOP,AOP底層用的是動(dòng)態(tài)代理。所以spring 在掃描bean的時(shí)候會(huì)掃描方法上是否包含@Transactional注解,如果包含,spring會(huì)為這個(gè)bean動(dòng)態(tài)地生成一個(gè)子類(即代理類,proxy),代理類是繼承原來(lái)那個(gè)bean的。

此時(shí),當(dāng)這個(gè)有注解的方法被調(diào)用的時(shí)候,實(shí)際上是由代理類來(lái)調(diào)用的,代理類在調(diào)用之前就會(huì)啟動(dòng)transaction。如果是被同一個(gè)類中的其他方法調(diào)用的,那么該方法的調(diào)用并沒(méi)有通過(guò)代理類,而是直接通過(guò)原來(lái)的那個(gè)bean,所以就不會(huì)啟動(dòng)transaction,我們說(shuō)只有一個(gè)事務(wù)。

8. 那么如何才能讓上面兩個(gè)方法開(kāi)啟兩個(gè)事務(wù)呢?

1.把方法B抽離到另外一個(gè)XXService中去,在這個(gè)Service中注入XXService,使用XXService調(diào)用方法B;

2.通過(guò)在方法內(nèi)部獲得當(dāng)前類代理對(duì)象的方式,通過(guò)代理對(duì)象調(diào)用方法B

上面說(shuō)了:動(dòng)態(tài)代理最終都是要調(diào)用原始對(duì)象的,而原始對(duì)象在去調(diào)用方法時(shí),是不會(huì)再觸發(fā)代理了!所以我們就使用代理對(duì)象來(lái)調(diào)用,就會(huì)觸發(fā)事務(wù);

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

1.使用 ApplicationContext 上下文對(duì)象獲取該對(duì)象;

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

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

testService.B();

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

9. @Transactional實(shí)現(xiàn)原理

注解介紹

@Transactional是spring中聲明式事務(wù)管理的注解配置方式。@Transactional注解可以幫助我們把事務(wù)開(kāi)啟、提交或者回滾的操作,通過(guò)aop的方式進(jìn)行管理。

通過(guò)@Transactional注解就能讓spring為我們管理事務(wù),免去了重復(fù)的事務(wù)管理邏輯,減少對(duì)業(yè)務(wù)代碼的侵入,使我們開(kāi)發(fā)人員能夠?qū)W⒂跇I(yè)務(wù)層面開(kāi)發(fā)。

我們知道實(shí)現(xiàn)@Transactional原理是基于spring aop,aop又是動(dòng)態(tài)代理模式的實(shí)現(xiàn),下面我們就詳細(xì)分析一下實(shí)現(xiàn)原理

實(shí)現(xiàn)原理

猜想

  • 首先,對(duì)于spring中aop實(shí)現(xiàn)原理有了解的話,應(yīng)該知道想要對(duì)一個(gè)方法進(jìn)行代理的話,肯定需要定義切點(diǎn)。在@Transactional的實(shí)現(xiàn)中,同樣如此,spring為我們定義了以 @Transactional 注解為植入點(diǎn)的切點(diǎn),這樣才能知道@Transactional注解標(biāo)注的方法需要被代理。
  • 有了切面定義之后,在spring的bean的初始化過(guò)程中,就需要對(duì)實(shí)例化的bean進(jìn)行代理,并且生成代理對(duì)象。
  • 生成代理對(duì)象的代理邏輯中,進(jìn)行方法調(diào)用時(shí),需要先獲取切面邏輯,@Transactional注解的切面邏輯類似于@Around,在spring中是實(shí)現(xiàn)一種類似代理邏輯。

源碼分析

  • 在配置好注解驅(qū)動(dòng)方式的事務(wù)管理之后,spring會(huì)在ioc容器創(chuàng)建一個(gè)BeanFactoryTransactionAttributeSourceAdvisor實(shí)例,這個(gè)實(shí)例可以看作是一個(gè)切點(diǎn),在判斷一個(gè)bean在初始化過(guò)程中是否需要?jiǎng)?chuàng)建代理對(duì)象,都需要驗(yàn)證一次BeanFactoryTransactionAttributeSourceAdvisor是否是適用這個(gè)bean的切點(diǎn)。如果是,就需要?jiǎng)?chuàng)建代理對(duì)象,并且把BeanFactoryTransactionAttributeSourceAdvisor實(shí)例注入到代理對(duì)象中。
  • 分析代理的對(duì)象發(fā)現(xiàn),最終的代理對(duì)象的代理方法是DynamicAdvisedInterceptor#intercept,分析這個(gè)方法后發(fā)現(xiàn)他最終調(diào)用的是TransactionInterceptor#invoke方法,并且把CglibMethodInvocation注入到invoke方法中,從上面可以看到CglibMethodInvocation是包裝了目標(biāo)對(duì)象的方法調(diào)用的所有必須信息,因此,在TransactionInterceptor#invoke里面也是可以調(diào)用目標(biāo)方法的,并且還可以實(shí)現(xiàn)類似@Around的邏輯,在目標(biāo)方法調(diào)用前后繼續(xù)注入一些其他邏輯,比如事務(wù)管理邏輯。
  • 當(dāng)我們調(diào)進(jìn)去TransactionInterceptor#invoke方法發(fā)現(xiàn)其中的核心方法是invokeWithinTransaction。

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2021-06-26 14:59:13

SpringTransaction執(zhí)行

2023-11-02 07:52:30

Java工具

2023-09-27 16:22:51

SpringMySQL原子性

2021-04-14 15:17:08

Transaction代碼語(yǔ)言

2023-09-28 09:07:54

注解失效場(chǎng)景

2025-01-16 08:45:48

2022-09-20 22:27:08

事務(wù)失效public 修飾

2022-09-14 19:50:22

事務(wù)場(chǎng)景流程

2023-04-02 13:57:04

Java自定義事務(wù)管理器

2022-08-08 17:38:45

Spring策略事務(wù)

2025-01-06 09:26:49

2022-08-09 09:34:32

Spring開(kāi)發(fā)

2023-08-31 08:12:23

應(yīng)用場(chǎng)景業(yè)務(wù)異常HTTP

2021-03-10 10:55:51

SpringJava代碼

2020-11-17 08:28:55

數(shù)據(jù)庫(kù)

2021-11-29 06:57:50

并行Stream Spring

2020-10-19 11:05:17

SpringTransaction事務(wù)

2022-02-14 16:53:57

Spring項(xiàng)目數(shù)據(jù)庫(kù)

2018-11-16 15:35:10

Spring事務(wù)Java

2020-08-19 09:45:29

Spring數(shù)據(jù)庫(kù)代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 亚洲一区亚洲二区 | 国产91色在线 | 亚洲 | 在线视频中文字幕 | 国产成人综合av | 精品国产31久久久久久 | 日韩天堂av | 日本一区二区不卡视频 | 欧美一区二区 | 国产成人精品免费视频大全最热 | 在线一区视频 | 久久精品免费观看 | 成人在线免费电影 | 精品产国自在拍 | 手机看黄av免费网址 | 国产不卡一区 | av网站在线看 | 精品国产一级 | 国产精品久久久久久av公交车 | 亚洲一区二区三区视频 | 中文字幕第5页 | 久久久久亚洲av毛片大全 | 天天插天天射天天干 | 国产国产精品久久久久 | 久久看精品 | 久久99蜜桃综合影院免费观看 | 国产精品一区二区在线播放 | 国产精品片aa在线观看 | 中文字幕一区二区三区四区五区 | 欧美日韩不卡合集视频 | 日日碰碰 | 久久精品视频一区二区三区 | 国产精品不卡一区 | 日韩国产欧美在线观看 | 国产性色视频 | 啪啪综合网 | 久久成人国产 | av影音资源 | 一区二区免费视频 | 国产在线精品一区二区三区 | 伦理午夜电影免费观看 | 久久av.com|