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。

推薦閱讀: