Spring聲明式事務註解之@EnableTransactionManagement解析
Spring聲明式事務註解之@EnableTransactionManagement
1. 說明
@EnableTransactionManagement聲明在主配置類上,表示開啟聲明式事務,其原理是通過@Import導入TransactionManagementConfigurationSelector組件,然後又通過TransactionManagementConfigurationSelector導入組件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;
2. 原理分析
@EnableTransactionManagement代碼實現如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented // 通過@Import導入TransactionManagementConfigurationSelector組件 @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE; }
@EnableTransactionManagement通過@Import導入TransactionManagementConfigurationSelector;
TransactionManagementConfigurationSelector的實現如下:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { /** * {@inheritDoc} * @return {@link ProxyTransactionManagementConfiguration} or * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: // 根據@EnableTransactionManagement的固定值PROXY,這裡會導入AutoProxyRegistrar組件和ProxyTransactionManagementConfiguration組件 return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } }
所以TransactionManagementConfigurationSelector又導入瞭組件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;
3. AutoProxyRegistrar分析
3.1 AutoProxyRegistrar繼承關系
InfrastructureAdvisorAutoProxyCreator --AbstractAdvisorAutoProxyCreator --AbstractAdvisorAutoProxyCreator --ProxyProcessorSupport --SmartInstantiationAwareBeanPostProcessor // 跟AOP是原理是一樣的 --InstantiationAwareBeanPostProcessor --BeanPostProcessor --BeanFactoryAware
3.2 AutoProxyRegistrar的所用
AutoProxyRegistrar的作用跟AOP中的AnnotationAwareAspectJAutoProxyCreator是一樣的,利用後置處理器機制在對象創建以後,包裝對象,返回一個代理對象(增強器),代理對象執行方法利用攔截器鏈進行調用;InfrastructureAdvisorAutoProxyCreator繼承SmartInstantiationAwareBeanPostProcessor,跟AOP的原理是一樣的,也是通過@Transactional作為方法攔截的標記,把有事務管理的類作為目標類,生成代理對象,然後增強@Transactional標記的方法,在使用目標方法的時候,從IOC容器中獲取的其實是被增強的代理類,且事務方法會被代理,跟AOP原理一樣的;
4. ProxyTransactionManagementConfiguration分析
ProxyTransactionManagementConfiguration是一個配置類,想IOC容器中導入事務增強器(BeanFactoryTransactionAttributeSourceAdvisor),事務註解@Transactional的解析器(AnnotationTransactionAttributeSource)和事務方法攔截器(TransactionInterceptor);
package org.springframework.transaction.annotation; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Role; import org.springframework.transaction.config.TransactionManagementConfigUtils; import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor; import org.springframework.transaction.interceptor.TransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionInterceptor; @Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { /** 事務增強器(Advisor),在事務類創建的時候,被AutoProxyRegistrar導入的組件InfrastructureAdvisorAutoProxyCreator攔截, InfrastructureAdvisorAutoProxyCreator攔截的邏就是增強事務類的事務方法, 而BeanFactoryTransactionAttributeSourceAdvisor作為增強器, 與需要增強的方法(這裡是指被@Transactional標記的方法)進行匹配,匹配成功的增強器,最後轉成攔截器(MethodInterceptor, 就是下面的TransactionInterceptor),然後與目標方法一起在攔截器鏈中被執行,達到方法增強的效果; BeanFactoryTransactionAttributeSourceAdvisor的繼承關系如下: BeanFactoryTransactionAttributeSourceAdvisor --AbstractBeanFactoryPointcutAdvisor --AbstractPointcutAdvisor --PointcutAdvisor --Advisor AOP中AspectJPointcutAdvisor的繼承關系如下,與AbstractPointcutAdvisor一樣,都實現PointcutAdvisor --AspectJPointcutAdvisor --PointcutAdvisor --Advisor */ @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); advisor.setOrder(this.enableTx.<Integer>getNumber("order")); return advisor; } /** @Transactional註解的解析類;負責解析事務方法上@Transactional中的各個參數配置,解析的時機是在創建事務類之後被增強的時候, 匹配事務方法的時候一起被解析瞭 AnnotationTransactionAttributeSource的繼承關系如下: AnnotationTransactionAttributeSource --AbstractFallbackTransactionAttributeSource --TransactionAttributeSource 通過方法org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>) 解析出事務信息TransactionAttribute; AnnotationTransactionAttributeSource在方法findTransactionAttribute(Class<?>)中依賴於SpringTransactionAnnotationParser在解析事務類時, 綁定事務方法與增強器的時候進行@Transactional註解解析; */ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } /** 被@Transactional標記的事務方法的攔截器,實際是一個MethodInterceptor 保存瞭事務屬性信息,事務管理器; 在目標方法執行的時候;執行攔截器鏈; */ @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; } }
在SpringTransactionAnnotationParser中parseTransactionAnnotation方法來解析@Transactional中的各個參數,其具體代碼如下:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); Propagation propagation = attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); rbta.setQualifier(attributes.getString("value")); ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>(); Class<?>[] rbf = attributes.getClassArray("rollbackFor"); for (Class<?> rbRule : rbf) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] rbfc = attributes.getStringArray("rollbackForClassName"); for (String rbRule : rbfc) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } Class<?>[] nrbf = attributes.getClassArray("noRollbackFor"); for (Class<?> rbRule : nrbf) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] nrbfc = attributes.getStringArray("noRollbackForClassName"); for (String rbRule : nrbfc) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } rbta.getRollbackRules().addAll(rollBackRules); return rbta; }
spring 事務 @EnableTransactionManagement原理
@EnableXXX原理:註解上有個XXXRegistrar,或通過XXXSelector引入XXXRegistrar,XXXRegistrar實現瞭ImportBeanDefinitionRegistrar的registerBeanDefinitions方法,給容器註冊XXXCreator。
這個Creator實現瞭後置處理器,後置處理器在對象創建以後,包裝對象,返回一個代理對象,代理對象執行方法利用攔截器鏈進行調用
1)、@EnableTransactionManagement
利用TransactionManagementConfigurationSelector給容器中會導入組件
導入兩個組件
AutoProxyRegistrar ProxyTransactionManagementConfiguration
2)、AutoProxyRegistrar:
給容器中註冊一個 InfrastructureAdvisorAutoProxyCreator 組件;
利用後置處理器機制在對象創建以後,包裝對象,返回一個代理對象(增強器),代理對象執行方法利用攔截器鏈進行調用;
3)、ProxyTransactionManagementConfiguration是個@Configuration
1、給容器中註冊事務增強器transactionAdvisor;
1)、事務增強器要用事務註解的信息,AnnotationTransactionAttributeSource解析事務註解
2)、事務攔截器transactionInterceptor:
TransactionInterceptor;保存瞭事務屬性信息,事務管理器;
TransactionInterceptor是一個 MethodInterceptor;
在目標方法執行的時候;
執行攔截器鏈;
隻有事務攔截器:
1)、先獲取事務相關的屬性
2)、再獲取PlatformTransactionManager,如果事先沒有添加指定任何transactionmanger 最終會從容器中按照類型獲取一個PlatformTransactionManager;
3)、執行目標方法
如果異常,獲取到事務管理器,利用事務管理回滾操作;
如果正常,利用事務管理器,提交事務
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Spring深入刨析聲明式事務註解的源碼
- Spring事務的開啟原理詳解
- Java Spring AOP源碼解析之事務實現原理
- spring基於註解配置實現事務控制操作
- Spring事務執行流程及如何創建事務