Spring聲明式事務(wù)@Transactional注解實(shí)現(xiàn)元數(shù)據(jù)驅(qū)動的事務(wù)管理
@Transactional 注解元數(shù)據(jù)驅(qū)動的聲明式事務(wù)
基本原理
將對應(yīng)的方法通過注解元數(shù)據(jù),標(biāo)注在業(yè)務(wù)方法或者所在的對象上,然后在業(yè)務(wù)執(zhí)行期間,通過AOP攔截器反射讀取元數(shù)據(jù)信息,最終將根據(jù)讀取的業(yè)務(wù)信息構(gòu)建事務(wù)管理支持。
不同的方法之間的事務(wù)傳播保證在同一個事務(wù)內(nèi),是通過統(tǒng)一的數(shù)據(jù)源來實(shí)現(xiàn)的,事務(wù)開始時將數(shù)據(jù)源綁定到ThreadLocal中,后續(xù)加入的事務(wù)從ThreadLocal獲取數(shù)據(jù)源來保證數(shù)據(jù)源的統(tǒng)一。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { @AliasFor("transactionManager") String value() default ""; //事務(wù)管理器名稱 @AliasFor("value") String transactionManager() default ""; //事務(wù)傳播模式 Propagation propagation() default Propagation.REQUIRED; //事務(wù)隔離級別 Isolation isolation() default Isolation.DEFAULT; //超時時間 int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; //是否是只讀事務(wù) boolean readOnly() default false; //需要回滾的異常類 Class<? extends Throwable>[] rollbackFor() default {}; //需要回滾的異常類名稱 String[] rollbackForClassName() default {}; //排除回滾的異常類 Class<? extends Throwable>[] noRollbackFor() default {}; //排除回滾的異常類名稱 String[] noRollbackForClassName() default {}; }
SpringBoot代碼來分析
這里通過SpringBoot代碼來分析實(shí)現(xiàn)過程,源碼中刪除了部分代碼,只保留了一些重要部分
// 事務(wù)自動配置類 注意類里面使用的@EnableTransactionManagement注解 org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration public class TransactionAutoConfiguration { @Configuration @ConditionalOnBean(PlatformTransactionManager.class) @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class) public static class EnableTransactionManagementConfiguration { //注意這里使用的@EnableTransactionManagement注解 @Configuration @EnableTransactionManagement(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } //注意這里使用的@EnableTransactionManagement注解 @Configuration @EnableTransactionManagement(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } } }
這里只分析proxy模式
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } //這里注入了TransactionInterceptor攔截器bean~~~~ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
TransactionInterceptor攔截器通過元數(shù)據(jù)獲取事務(wù)定義信息TransactionDefinition,根據(jù)Definition信息獲取PlatformTransactionManager(TM),tm接口抽象了事務(wù)的實(shí)現(xiàn)流程,默認(rèn)的tm是DataSourceTransactionManager(通過DataSourceTransactionManagerAutoConfiguration初始化的),tm中的getTransaction根據(jù)事務(wù)的傳播方式,開啟、加入、掛起事務(wù)
@Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { // 使用默認(rèn)的Definition definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { //已經(jīng)存在事務(wù),進(jìn)入單獨(dú)的方法處理 return handleExistingTransaction(definition, transaction, debugEnabled); } // 檢查timeout參數(shù) if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // 當(dāng)前必須存在事務(wù),否則拋出異常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { //獲取當(dāng)前的一些事務(wù)信息,用于當(dāng)前事務(wù)執(zhí)行完后恢復(fù) SuspendedResourcesHolder suspendedResources = suspend(null); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //構(gòu)造一個新事務(wù)的TransactionStatus(包含嵌套事務(wù)SavePoint的支持) DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //開啟新的事務(wù) doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error ex) { //異常,恢復(fù)掛起的事務(wù)信息 resume(null, suspendedResources); throw ex; } } else { //空的事務(wù) boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
以上就是Spring聲明式事務(wù)@Transactional注解實(shí)現(xiàn)元數(shù)據(jù)驅(qū)動的事務(wù)管理的詳細(xì)內(nèi)容,更多關(guān)于Spring @Transactional事務(wù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java利用數(shù)組隨機(jī)抽取幸運(yùn)觀眾如何實(shí)現(xiàn)
這篇文章主要介紹了Java利用數(shù)組隨機(jī)抽取幸運(yùn)觀眾如何實(shí)現(xiàn),需要的朋友可以參考下2014-02-02Spring 使用 feign時設(shè)置header信息的操作
這篇文章主要介紹了Spring 使用 feign時設(shè)置header信息的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Spring的循環(huán)依賴、三級緩存解決方案源碼詳細(xì)解析
這篇文章主要介紹了Spring的循環(huán)依賴、三級緩存解決方案源碼詳細(xì)解析,在Spring中,由于IOC的控制反轉(zhuǎn),創(chuàng)建對象不再是簡單的new出來,而是交給Spring去創(chuàng)建,會經(jīng)歷一系列Bean的生命周期才創(chuàng)建出相應(yīng)的對象,需要的朋友可以參考下2024-01-01java對于目錄下文件的單詞查找操作代碼實(shí)現(xiàn)
這篇文章主要介紹了java對于目錄下文件的單詞查找操作代碼實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11Spring Boot + Mybatis 實(shí)現(xiàn)動態(tài)數(shù)據(jù)源案例分析
這篇文章主要介紹了Spring Boot + Mybatis 實(shí)現(xiàn)動態(tài)數(shù)據(jù)源,需要的朋友可以參考下2018-11-11淺談Java list.remove( )方法需要注意的兩個坑
這篇文章主要介紹了淺談Java list.remove( )方法需要注意的兩個坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12SpringBoot中的@RequestMapping注解的用法示例
@RequestMapping注解是SpringBoot中最常用的注解之一,它可以幫助開發(fā)者定義和處理HTTP請求,本篇文章我們將詳細(xì)為大家介紹如何使用SpringBoot中的@RequestMapping注解,感興趣的同學(xué)跟著小編一起來學(xué)習(xí)吧2023-06-06