欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

【面試】Spring事務(wù)面試考點(diǎn)吐血整理(建議珍藏)

 更新時(shí)間:2019年04月16日 11:34:58   作者:李新杰  
本文是小編給大家收藏整理的Spring事務(wù)面試考點(diǎn),非常不錯(cuò),值得收藏,感興趣的朋友參考下吧

Starting from a joke

問:把大象放冰箱里,分幾步?

答:三步啊,第一、把冰箱門打開,第二、把大象放進(jìn)去,第三、把冰箱門帶上。

問:實(shí)現(xiàn)Spring事務(wù),分幾步?

答:三步啊,第一、找出需要事務(wù)的方法,第二、把事務(wù)加進(jìn)去,第三、執(zhí)行事務(wù)。

You may find it's not a joke, it's serious。

Try to find an entrance

當(dāng)你面對(duì)一個(gè)完全不熟悉的事物時(shí),一定要想辦法找到一個(gè)突破口,然后逐步深入。那Spring事物的突破口在哪里呢?很明顯在@EnableTransactionManagement注解里,因?yàn)槭撬鼏⒂昧耸挛锕δ堋?/p>

請(qǐng)看下圖:

發(fā)現(xiàn)注解還引入了一個(gè)類TransactionManagementConfigurationSelector。

再來看這個(gè)類,如下圖:

發(fā)現(xiàn)如果采用代理的方式時(shí),又引入了一個(gè)類ProxyTransactionManagementConfiguration。

接著看這個(gè)類(重點(diǎn)來了),如下圖:

發(fā)現(xiàn)這個(gè)類往容器中注冊(cè)了3個(gè)bean,第一個(gè)是BeanFactoryTransactionAttributeSourceAdvisor。它以Advisor結(jié)尾說明它是Spring AOP范疇里的東西。

在AOP里,Advisor = Pointcut + Advice,Pointcut是切入點(diǎn),表示要攔截的方法,Advice是增強(qiáng),表示要加進(jìn)去的事物功能。

再看看另外兩個(gè)注冊(cè)的bean,就是和這兩個(gè)相關(guān)的。其中TransactionInterceptor就是一個(gè)Advice,因?yàn)樗鼘?shí)現(xiàn)了Advice接口,包含了把事物加進(jìn)去的邏輯。

TransactionAttributeSource雖然不是一個(gè)Pointcut,但是它被Pointcut所用,用于檢測(cè)一個(gè)類的方法上是否有@Transactional注解,來確定該方法是否需要事物增強(qiáng)。

從下圖中也可以看出這一點(diǎn):

可以看到這個(gè)bean通過下面的set方法被設(shè)置進(jìn)去,然后又用在了Pointcut的類里了。

整體來看,此部分的結(jié)構(gòu)和功能劃分還是非常清晰的。下面來逐一研究。

AOP切點(diǎn)

TransactionAttributeSourcePointcut類以Pointcut結(jié)尾,說明它是一個(gè)切入點(diǎn),就是標(biāo)識(shí)要被攔截的方法。類名的前綴部分表明了這個(gè)切入點(diǎn)的實(shí)現(xiàn)原理。

看下這個(gè)前綴是TransactionAttributeSource,它以Source結(jié)尾,說明它是一個(gè)源(即源泉,有向外提供東西的意思)。它的前綴是TransactionAttribute,即事務(wù)屬性。

由此可見,這個(gè)源可以向外提供事務(wù)屬性,其實(shí)就是判斷一個(gè)類的方法上是否標(biāo)有@Transactional注解,如果有的話還可以獲取這個(gè)注解的屬性(即事務(wù)屬性)。

整體來說就是,Pointcut攔截住了方法,然后使用這個(gè)“源”去方法和類上獲取事務(wù)屬性,如果能獲取到,說明此方法需要參與事務(wù),則進(jìn)行事務(wù)增強(qiáng),反之則不增強(qiáng)。

下面這張圖可以證明我們的想法:

可以看出matches方法的兩個(gè)參數(shù)就是一個(gè)方法(Method)和一個(gè)類(Class<?>)。最后從方法和類上獲取事務(wù)屬性,再進(jìn)行是否為null判斷。

現(xiàn)在這個(gè)“源”還是個(gè)黑盒子,下面來揭開它的面紗。它的實(shí)現(xiàn)類是AnnotationTransactionAttributeSource,以Annotation開頭,說明是基于注解實(shí)現(xiàn)的。

下面圖是它的源碼的一部分:

第一個(gè)方法從類上找事務(wù)屬性,第二個(gè)方法從方法上找事務(wù)屬性,它倆都調(diào)用了第三個(gè)方法來實(shí)現(xiàn)。

PS:我們都知道,方法上的注解優(yōu)先級(jí)高于類上的,是因?yàn)檎易⒔鈺r(shí)先找方法上的,找不到時(shí)再去類上找。所以方法上的優(yōu)先級(jí)高。此部分代碼邏輯在父類里寫著呢,這里不再展示了。

第三個(gè)方法使用多個(gè)事務(wù)注解解析器(TransactionAnnotationParser)去解析注解,為啥是多個(gè)解析器呢?因?yàn)槭聞?wù)注解不僅Spring提供了,Java后來也提供了,就是javax.transaction.Transactional。

Spring對(duì)自己注解的解析器實(shí)現(xiàn)類是SpringTransactionAnnotationParser,如下圖:

可以看出使用工具類來讀取注解@Transactional的屬性,然后逐個(gè)解析出屬性值并進(jìn)行類型轉(zhuǎn)換,接著把這些屬性封裝到一個(gè)類里,這個(gè)類其實(shí)就是事務(wù)屬性,即TransactionAttribute。

這個(gè)事務(wù)屬性繼承了事務(wù)定義接口,事務(wù)定義接口我們應(yīng)該都很熟悉,如下圖:

這也證明了以前文章里說過的話,@Transactional注解的作用有兩個(gè),一是表明要參與事務(wù),二是表明如何參與事務(wù),這些注解屬性就是來規(guī)定如何參與的。

這個(gè)事務(wù)屬性TransactionAttribute是個(gè)接口,它的實(shí)現(xiàn)類在這里就不再詳說了。

AOP增強(qiáng)

Advice就是AOP中的增強(qiáng),TransactionInterceptor實(shí)現(xiàn)了Advice接口,所以它就是事務(wù)增強(qiáng)。

先來看下該接口,如下圖:

發(fā)現(xiàn)它只是一個(gè)空的標(biāo)記接口。而且它的包名是org.aopalliance,是一個(gè)AOP聯(lián)盟組織,它制定的AOP規(guī)范。

先來了解下AOP領(lǐng)域的一些相關(guān)內(nèi)容,Pointcut是切入點(diǎn),表示要攔截的方法。它是一個(gè)靜態(tài)的概念,即程序不運(yùn)行時(shí)它也是存在的。

那么在真正運(yùn)行時(shí),已經(jīng)攔截住了,此時(shí)該怎么表示這個(gè)情況呢?是用Joinpoint來表示的,所以Joinpoint是一個(gè)運(yùn)行時(shí)的概念,只有在運(yùn)行時(shí)才存在。

請(qǐng)看Joinpoint接口,如下圖:

第一個(gè)方法proceed()是“繼續(xù)”的意思,調(diào)用它表示去執(zhí)行被攔截住的方法本身,返回方法本身的返回值。

第二個(gè)方法getThis()是獲取this對(duì)象,即方法運(yùn)行時(shí)所在的目標(biāo)對(duì)象。如果是靜態(tài)方法,則為null,因?yàn)殪o態(tài)方法是屬于類本身的,運(yùn)行時(shí)不需要對(duì)象。

第三個(gè)方法getStaticPart(),其實(shí)就表示了被攔截住的方法,即就是一個(gè)Method。Method其實(shí)算是“元數(shù)據(jù)”,是屬于類型本身的,也有“靜態(tài)”的意思。

再看一個(gè)接口,Invocation,它繼承了Joinpoint,如下圖:

方法getArguments()就表示運(yùn)行時(shí)傳遞給被攔截住方法的參數(shù)。

再看一個(gè)接口,MethodInvocation,它繼承了Invocation,如下圖:

方法getMethod()返回一個(gè)Method,它就是當(dāng)前正在執(zhí)行的方法,是對(duì)本攔截方法的一個(gè)友好實(shí)現(xiàn),返回相同的結(jié)果。

可見MethodInvocation接口已經(jīng)包含了一個(gè)方法調(diào)用的全量信息,方法,參數(shù),目標(biāo)對(duì)象。這其實(shí)就是運(yùn)行時(shí)被攔截住的東西。

再看下面這個(gè)接口,MethodInterceptor,方法攔截器,如下圖:

它只有一個(gè)方法invoke,方法參數(shù)就是上面介紹的MethodInvocation。所以攔截器可以使用這個(gè)參數(shù)來對(duì)目標(biāo)方法進(jìn)行調(diào)用,當(dāng)然在調(diào)用前/后可以加入自己的邏輯。

TransactionInterceptor類就實(shí)現(xiàn)了這個(gè)接口,因此可以在對(duì)目標(biāo)方法的調(diào)用前后插入事務(wù)邏輯代碼來進(jìn)行事務(wù)增強(qiáng)。

下面是事務(wù)攔截器對(duì)該方法的實(shí)現(xiàn),如下圖:

它調(diào)用的invokeWithinTransaction方法是在父類里的,看下圖:

這個(gè)圖里做的事情較多,逐個(gè)來看:

前兩行獲取事務(wù)屬性“源”,再用這個(gè)“源”來獲取事務(wù)屬性。咦,有點(diǎn)奇怪,上面不是已經(jīng)獲取過了嗎?是的,上面是在Pointcut里獲取的,那只是用于判斷那個(gè)方法是否要被攔截而已。這里獲取的屬性才是真正用于事務(wù)的。

第三行是根據(jù)事務(wù)屬性,來確定出一個(gè)事務(wù)管理器來。

接下來是使用事務(wù)管理器打開事務(wù)。

接下來是對(duì)被攔截住的目標(biāo)方法的調(diào)用執(zhí)行,當(dāng)然要try/catch住這個(gè)執(zhí)行。

如果拋出了異常,則進(jìn)行和異常相關(guān)的事務(wù)處理,然后將這個(gè)異常繼續(xù)向上拋出。

如果沒有拋出異常,則進(jìn)行事務(wù)提交。

最后的else分支是對(duì)編程式事務(wù)的調(diào)用,事務(wù)的打開/提交/回滾是開發(fā)人員自己寫代碼控制,所以就不需要事務(wù)管理器操心了。

下面請(qǐng)看和異常相關(guān)的事務(wù)處理,如下圖:

判斷異常類型是否需要回滾,需要的話就回滾事務(wù),不需要的話就繼續(xù)提交事務(wù)。

這里的整體結(jié)構(gòu)和邏輯流程也是比較清晰的,那是因?yàn)橐环矫娴靡嬗贏OP領(lǐng)域的概念,另一方面是事務(wù)管理器屏蔽了事務(wù)的所有復(fù)雜性。

PS:事務(wù)管理器的內(nèi)容其實(shí)還是挺復(fù)雜的,下篇文章再詳細(xì)解說。

好了,以上是小編給大家介紹的Spring事務(wù)面試整理,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

相關(guān)文章

  • springboot自帶線程池ThreadPoolTaskExecutor使用

    springboot自帶線程池ThreadPoolTaskExecutor使用

    本文主要介紹了springboot自帶線程池ThreadPoolTaskExecutor使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • SpringBoot @PropertySource與@ImportResource有什么區(qū)別

    SpringBoot @PropertySource與@ImportResource有什么區(qū)別

    這篇文章主要介紹了SpringBoot @PropertySource與@ImportResource有什么區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01
  • Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解

    Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解

    使用Spring Boot開發(fā)API的時(shí)候,讀取請(qǐng)求參數(shù)是服務(wù)端編碼中最基本的一項(xiàng)操作,Spring Boot中也提供了多種機(jī)制來滿足不同的API設(shè)計(jì)要求,這篇文章主要介紹了Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解,需要的朋友可以參考下
    2024-05-05
  • Java如何使用elasticsearch進(jìn)行模糊查詢

    Java如何使用elasticsearch進(jìn)行模糊查詢

    這篇文章主要介紹了Java如何使用elasticsearch進(jìn)行模糊查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot?熱搜與不雅文字過濾的實(shí)現(xiàn)

    SpringBoot?熱搜與不雅文字過濾的實(shí)現(xiàn)

    本文主要介紹了SpringBoot?熱搜與不雅文字過濾的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java計(jì)算器核心算法代碼實(shí)現(xiàn)

    Java計(jì)算器核心算法代碼實(shí)現(xiàn)

    今天小編就為大家分享一篇關(guān)于Java計(jì)算器核心算法代碼實(shí)現(xiàn),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 談?wù)勗贘ava發(fā)送郵件中遇到的的問題

    談?wù)勗贘ava發(fā)送郵件中遇到的的問題

    本文介紹了在利用Java發(fā)送郵件過程中遇到的的兩個(gè)問題,以及如何解決這兩個(gè)問題。如果大家也遇到了這些問題,可以來參考借鑒。
    2016-08-08
  • Java中的Sentinel規(guī)則持久化詳解

    Java中的Sentinel規(guī)則持久化詳解

    這篇文章主要介紹了Java中的Sentinel規(guī)則持久化詳解,將限流配置規(guī)則持久化進(jìn)Nacos保存,只要刷新8401某個(gè)rest地址,sentinel控制臺(tái)的流控規(guī)則就能看到,只要Nacos里面的配置不刪除,針對(duì)8401上sentinel上的流控規(guī)則持續(xù)有效,需要的朋友可以參考下
    2023-09-09
  • Springmvc應(yīng)用Mongodb分頁實(shí)現(xiàn)

    Springmvc應(yīng)用Mongodb分頁實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Springmvc應(yīng)用Mongodb分頁實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java中的位運(yùn)算符號(hào)解讀(&、|、^、~、<<、>>、>>>)

    Java中的位運(yùn)算符號(hào)解讀(&、|、^、~、<<、>>、>>>)

    這篇文章主要介紹了Java中的位運(yùn)算符號(hào)(&、|、^、~、<<、>>、>>>),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論