spring聲明式事務(wù)@Transactional底層工作原理
引言
寫(xiě)這篇博文有個(gè)來(lái)由,是為了解決博主遇到的多數(shù)據(jù)源的事務(wù)問(wèn)題(用不了JTA),所以深入到spring-tx的源碼去學(xué)習(xí)了一番,非常有收獲,最后博主的分布式事務(wù)問(wèn)題也迎刃而解了,這個(gè)文章算個(gè)開(kāi)篇,關(guān)于如何處理多數(shù)據(jù)源事務(wù),待下文分解。本文涉及到的技術(shù)包含spring aop的使用、spring bean生命周期等,如果能夠真正理解Transactional的工作原理,對(duì)排查事務(wù)相關(guān)的問(wèn)題有非常大的幫助。
spring-tx版本:5.0.2
工作機(jī)制簡(jiǎn)述
先來(lái)看一張官方的事務(wù)簡(jiǎn)圖:
spring定義了@Transactional注解,基于AbstractBeanFactoryPointcutAdvisor、StaticMethodMatcherPointcut、MethodInterceptor的aop編程模式,增強(qiáng)了添加@Transactional注解的方法。同時(shí)抽象了事務(wù)行為為PlatformTransactionManager(事務(wù)管理器)、TransactionStatus(事務(wù)狀態(tài))、TransactionDefinition(事務(wù)定義)等形態(tài)。最終將事務(wù)的開(kāi)啟、提交、回滾等邏輯嵌入到被增強(qiáng)的方法的前后,完成統(tǒng)一的事務(wù)模型管理。
事務(wù)AOP核心類(lèi)釋義
@Transactional
事務(wù)注解,用于定位aop的切入點(diǎn),事務(wù)注解里包含了完整事務(wù)的所有基本屬性,常見(jiàn)的屬性如:
transactionManager
:事務(wù)管理器
propagation
:傳播行為定義,枚舉類(lèi)型,是spring獨(dú)有的事務(wù)行為設(shè)計(jì),默認(rèn)為PROPAGATION_REQUIRED(支持當(dāng)前事務(wù),不存在則新建)
isolation
:隔離級(jí)別,對(duì)應(yīng)數(shù)據(jù)庫(kù)的隔離級(jí)別實(shí)現(xiàn),mysql默認(rèn)的隔離級(jí)別是 read-committed
timeout
:超時(shí)時(shí)間,默認(rèn)使用數(shù)據(jù)庫(kù)的超時(shí),mysql默認(rèn)的事務(wù)等待超時(shí)為5分鐘
readOnly
:是否只讀,默認(rèn)是false
rollbackFor
:異?;貪L列表,默認(rèn)的是RuntimeException異?;貪L
TransactionAttribute
事務(wù)屬性抽象接口類(lèi),承載了@Transactional注解里的所有屬性,實(shí)現(xiàn)類(lèi)的繼承關(guān)系如下類(lèi)結(jié)構(gòu)圖,這個(gè)實(shí)例在被注解解析器創(chuàng)建好后,會(huì)在事務(wù)上下文中傳遞
SpringTransactionAnnotationParser
見(jiàn)名知意,這個(gè)類(lèi)是spring的事務(wù)注解解析器,實(shí)現(xiàn)自TransactionAnnotationParser接口,是spring管理的事務(wù)解析器,用于解析@Transactional注解,將注解里的屬性設(shè)置到TransactionAttribute的實(shí)現(xiàn)類(lèi)屬性里。除了這個(gè),另還有兩個(gè)實(shí)現(xiàn),分別是JTA事務(wù)注解解析器,和EJB事務(wù)注解管理解析器,區(qū)別是解析的注解不同,spring是@Transactional,jta是javax.transaction.Transactional,EJB是javax.ejb.TransactionAttribute。這個(gè)地方應(yīng)用和apache dubbo2.7.x版本解析dubbo的@service注解是一樣一樣的。關(guān)鍵代碼如下,通過(guò)AnnotatedElementUtils類(lèi),這個(gè)類(lèi)在spring-core包下,找到注解屬性集AnnotationAttributes,如果不為空,則包裝成事務(wù)屬性集返回
@Override @Nullable public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( element, Transactional.class, false, false); if (attributes != null) { return parseTransactionAnnotation(attributes); } else { return null; } }
AnnotationTransactionAttributeSource
見(jiàn)名知意,這個(gè)類(lèi)是注解事務(wù)屬性集的源,怎么理解呢?spring抽象了獲取事務(wù)屬性集的行為,而AnnotationTransactionAttributeSource正是@Transactional注解方式的事務(wù)屬性集收集實(shí)現(xiàn)。SpringTransactionAnnotationParser就是作用于這個(gè)里面,用于發(fā)現(xiàn)@Transactiona注解的方法
TransactionAttributeSourcePointcut
也是見(jiàn)名知意,Pointcut屬于aop的概念范疇,需要了解spring aop的知識(shí)才能看明白,這個(gè)就是@Transactional注解的切點(diǎn),AnnotationTransactionAttributeSource作用于此,用于尋找@Transactiona注解的方法,關(guān)鍵代碼如下:
public boolean matches(Method method, Class targetClass) { TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
TransactionInterceptor
事務(wù)的攔截器。aop編程里,有了切入點(diǎn)Pointcut,就要有通知advice,我們熟悉的spring aop里有前置、后置、環(huán)繞、異常等通知類(lèi)型,TransactionInterceptor屬于自定義通知模型實(shí)現(xiàn),實(shí)現(xiàn)自Advice接口,類(lèi)似于環(huán)繞通知,具體見(jiàn)類(lèi)結(jié)構(gòu)圖,如下:
核心方法如下:
public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
被@Transactional注解的方法,如果被aop正確的增強(qiáng)了,運(yùn)行的時(shí)候都會(huì)進(jìn)入到這個(gè)方法里面,如果你發(fā)現(xiàn)事務(wù)不生效啊等等問(wèn)題,可以從這里開(kāi)始定位真實(shí)原因
BeanFactoryTransactionAttributeSourceAdvisor
事務(wù)增強(qiáng)器,用于增強(qiáng)添加了@Transactional注解的方法,上面提到的這些核心類(lèi),最終都作用于這里,用于尋找@Transactional注解的方法和織入事務(wù)處理邏輯
ProxyTransactionManagementConfiguration
代理事務(wù)管理的配置類(lèi),上面介紹的這些事務(wù)aop編程相關(guān)的在這個(gè)里面組合配置生效的,同時(shí),如果你有特殊的個(gè)性化的需求,也可以自定義注冊(cè)這個(gè)里面的實(shí)例。比如我嫌棄@Transactional注解太長(zhǎng)了,想用@Tx注解。沒(méi)關(guān)系,直接定義個(gè)TransactionAttributeSource實(shí)現(xiàn),解析@Tx的方法,然后注冊(cè)到spring的上線(xiàn)文中即可。代碼如:
@Configuration(proxyBeanMethods = false) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor( TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this.enableTx != null) { advisor.setOrder(this.enableTx.getNumber("order")); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor( TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
事務(wù)抽象核心類(lèi)釋義
PlatformTransactionManager
平臺(tái)事務(wù)管理器,這是Spring事務(wù)基礎(chǔ)設(shè)施中的中心接口。它定義了三個(gè)最最基本的事務(wù)方法,getTransaction獲取事務(wù),包含了事務(wù)開(kāi)啟的行為,commit提交事務(wù),rollback回滾事務(wù)。代碼如下:
public interface PlatformTransactionManager extends TransactionManager { TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
在spring-tx中并沒(méi)有提供真正的實(shí)現(xiàn)類(lèi),只提供了一個(gè)抽象派生類(lèi)AbstractPlatformTransactionManager,并建議其他實(shí)現(xiàn)基于這個(gè)派生類(lèi),因?yàn)樗A(yù)先實(shí)現(xiàn)了定義的傳播行為并處理事務(wù)同步處理。子類(lèi)必須為底層事務(wù)的特定狀態(tài)實(shí)現(xiàn)模板方法,例如:begin、suspend、resume、commit等。我們平時(shí)常見(jiàn)的實(shí)現(xiàn)有:JpaTransactionManager、JtaTransactionManager、DataSourceTransactionManager等。事務(wù)管理器和事務(wù)aop處理的邏輯本身沒(méi)有任何耦合,只需將PlatformTransactionManager實(shí)例注冊(cè)到spring上下文中即可,事務(wù)攔截器會(huì)通過(guò)獲取到@Transactional里的transactionManager屬性去上下文中尋找事務(wù)管理器,并將其緩存起來(lái),見(jiàn)TransactionAspectSupport.java里的determineTransactionManager方法
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) { // Do not attempt to lookup tx manager if no tx attributes are set if (txAttr == null || this.beanFactory == null) { return asPlatformTransactionManager(getTransactionManager()); } String qualifier = txAttr.getQualifier(); if (StringUtils.hasText(qualifier)) { return determineQualifiedTransactionManager(this.beanFactory, qualifier); } else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } else { PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager()); if (defaultTransactionManager == null) { defaultTransactionManager = asPlatformTransactionManager( this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY)); if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } } return defaultTransactionManager; } }
TransactionStatus
事務(wù)狀態(tài)抽象,用這個(gè)類(lèi)的實(shí)現(xiàn)來(lái)維護(hù)當(dāng)前的事務(wù)狀態(tài),spring-tx里提供了默認(rèn)的實(shí)現(xiàn)DefaultTransactionStatus。一般情況下這個(gè)不需要我們關(guān)心,它和PlatformTransactionManager是成對(duì)存在的,心細(xì)的你可能已經(jīng)發(fā)現(xiàn)了,PlatformTransactionManager里的三個(gè)事務(wù)行為傳遞的就是TransactionStatus。我們知道事務(wù)aop增強(qiáng)了添加@Transactional的方法,在執(zhí)行方法前調(diào)用PlatformTransactionManager.getTransaction開(kāi)啟事務(wù),之后調(diào)用commit方法提交事務(wù),提交事務(wù)的入?yún)ransactionStatus就是開(kāi)啟事務(wù)獲得的。參見(jiàn)TransactionAspectSupport.java里的createTransactionIfNecessary方法
TransactionDefinition
事務(wù)定義,對(duì)應(yīng)了TransactionAttribute,最終通過(guò)aop得到的TransactionAttribute里的屬性會(huì)被傳遞到TransactionDefinition里,所以TransactionDefinition里也包含了所有事務(wù)相關(guān)的屬性,PlatformTransactionManager.getTransaction正是通過(guò)這個(gè)里面的屬性去獲取的事務(wù)。AbstractPlatformTransactionManager派生類(lèi)里也是通過(guò)這個(gè)里面的屬性去判斷協(xié)調(diào)spring的事務(wù)傳播行為的
結(jié)語(yǔ)
當(dāng)梳理完spring-tx模塊的整個(gè)結(jié)構(gòu)和工作方式后,仿佛拉開(kāi)了spring事務(wù)管理的面紗,很多事務(wù)的執(zhí)行細(xì)節(jié)一覽無(wú)余。很多事務(wù)相關(guān)的問(wèn)題也就很容易解釋了。比如常見(jiàn)的類(lèi)中的方法直接調(diào)用方法事務(wù)不生效等問(wèn)題,以及可以非常清晰的理解spring的傳播行為的真正含義等。最后預(yù)告下,spring對(duì)于多數(shù)據(jù)源的事務(wù)處理解決方案ChainedTransactionManager
以上就是spring聲明式事務(wù)@Transactional底層工作原理的詳細(xì)內(nèi)容,更多關(guān)于spring聲明式事務(wù)@Transactional工作原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于集合和字符串的互轉(zhuǎn)實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇關(guān)于集合和字符串的互轉(zhuǎn)實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08詳解Spring boot+CXF開(kāi)發(fā)WebService Demo
這篇文章主要介紹了詳解Spring boot+CXF開(kāi)發(fā)WebService Demo,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05Intellij IDEA 關(guān)閉和開(kāi)啟自動(dòng)更新的提示?
這篇文章主要介紹了Intellij IDEA 關(guān)閉和開(kāi)啟自動(dòng)更新的提示操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04淺談Java中實(shí)現(xiàn)深拷貝的兩種方式—clone() & Serialized
這篇文章主要介紹了Java中實(shí)現(xiàn)深拷貝的兩種方式—clone() & Serialized,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03詳解spring boot實(shí)現(xiàn)多數(shù)據(jù)源代碼實(shí)戰(zhàn)
本篇文章主要介紹了詳解spring boot實(shí)現(xiàn)多數(shù)據(jù)源代碼實(shí)戰(zhàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Java的Hibernate框架中集合類(lèi)數(shù)據(jù)結(jié)構(gòu)的映射編寫(xiě)教程
Hibernate可以將Java中幾個(gè)內(nèi)置的集合結(jié)構(gòu)映射為數(shù)據(jù)庫(kù)使用的關(guān)系模型,下面我們就來(lái)看一下Java的Hibernate框架中集合類(lèi)數(shù)據(jù)結(jié)構(gòu)的映射編寫(xiě)教程:2016-07-07