Spring-事务

@EnableTransactionManagement工作原理

开启Spring事务本质上就是增加了一个Advisor,在使用@EnableTransactionManagement注解来开启Spring事务时,该注解代理的功能就是向Spring容器中添加了两个Bean

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement { ... }


/**
 * Selects which implementation of {@link AbstractTransactionManagementConfiguration}
 * should be used based on the value of {@link EnableTransactionManagement#mode} on the
 * importing {@code @Configuration} class.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see EnableTransactionManagement
 * @see ProxyTransactionManagementConfiguration
 * @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
 * @see TransactionManagementConfigUtils#JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
 */
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {

	/**
	 * Returns {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
	 * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
	 * respectively.
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				// 默认是PROXY
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				// 表示不用动态代理技术,用ASPECTJ技术,一般用不到
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

1、AutoProxyRegistrar

向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean

InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator

主要作用:开启自动代理

在初始化后寻找Advisor类型的Bean,并检查当前Bean是否有匹配的Advisor,是否需要动态代理创建代理对象

/**
 * Registers an auto proxy creator against the current {@link BeanDefinitionRegistry}
 * as appropriate based on an {@code @Enable*} annotation having {@code mode} and
 * {@code proxyTargetClass} attributes set to the correct values.
 *
 * @author Chris Beams
 * @since 3.1
 * @see org.springframework.cache.annotation.EnableCaching
 * @see org.springframework.transaction.annotation.EnableTransactionManagement
 */
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	/**
	 * Register, escalate, and configure the standard auto proxy creator (APC) against the
	 * given registry. Works by finding the nearest annotation declared on the importing
	 * {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
	 * attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
	 * {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
	 * subclass (CGLIB) proxying.
	 * 

Several {@code @Enable*} annotations expose both {@code mode} and * {@code proxyTargetClass} attributes. It is important to note that most of these * capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME * single APC}. For this reason, this implementation doesn't "care" exactly which * annotation it finds -- as long as it exposes the right {@code mode} and * {@code proxyTargetClass} attributes, the APC can be registered and configured all * the same. */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean candidateFound = false; Set annTypes = importingClassMetadata.getAnnotationTypes(); for (String annType : annTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (candidate == null) { continue; } Object mode = candidate.get("mode"); Object proxyTargetClass = candidate.get("proxyTargetClass"); if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { // 注册InfrastructureAdvisorAutoProxyCreator,才可以Bean进行AOP AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); if ((Boolean) proxyTargetClass) { // 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为true AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } if (!candidateFound && logger.isInfoEnabled()) { String name = getClass().getSimpleName(); logger.info(String.format("%s was imported but no annotations were found " + "having both 'mode' and 'proxyTargetClass' attributes of type " + "AdviceMode and boolean respectively. This means that auto proxy " + "creator registration and configuration may not have occurred as " + "intended, and components may not be proxied as expected. Check to " + "ensure that %s has been @Import'ed on the same class where these " + "annotations are declared; otherwise remove the import of %s " + "altogether.", name, name, name)); } } } // AopConfigUtils#registerAutoProxyCreatorIfNecessary public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAutoProxyCreatorIfNecessary(registry, null); } // AopConfigUtils#registerAutoProxyCreatorIfNecessary public static BeanDefinition registerAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); } // AopConfigUtils#forceAutoProxyCreatorToUseClassProxying public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { // AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator" if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); } }

2、ProxyTransactionManagementConfiguration

是一个配置类,内部定义了三个Bean:

  • BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor

  • AnnotationTransactionAttributeSource:相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut,判断某个类或者方法上面是否存在@Transactional注解,注意这里并没有解析

  • TransactionInterceptor:相当于BeanFactoryTransactionAttributeSourceAdvisor中的 Advice,当某个类中存在@Transactional注解,就会产生一个代理对象作为Bean,在执行代理对象的某个方法时会进入到TransactionInterceptor的invoke()方法中

invoke()方法里面就会创建数据库连接、关闭自动提交、事务提交和回滚等

/**
 * {@code @Configuration} class that registers the Spring infrastructure beans
 * necessary to enable proxy-based annotation-driven transaction management.
 *
 * @author Chris Beams
 * @author Sebastien Deleuze
 * @since 3.1
 * @see EnableTransactionManagement
 * @see TransactionManagementConfigurationSelector
 */
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
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() {
		// AnnotationTransactionAttributeSource中定义了一个Pointcut
		// 并且AnnotationTransactionAttributeSource可以用来解析@Transactional注解,并得到一个RuleBasedTransactionAttribute对象
		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;
	}

}

Spring事务基本执行原理

InfrastructureAdvisorAutoProxyCreator也是一个BeanPostProcessor(最终实现SmartInstantiationAwareBeanPostProcessor),在Bean的生命周期初始化后步骤时,会去判断是否需要创建代理对象

判断依据:当前Bean和BeanFactoryTransactionAttributeSourceAdvisor匹配,简单点就是当前Bean的类或者方法上面有没有@Transactional注解,有就匹配

在代理对象执行某个方法时,会再次判断当前执行方法和BeanFactoryTransactionAttributeSourceAdvisor是否匹配,如果匹配则执行该Advisor中的TransactionInterceptor的invoke()方法,执行流程:

(再次判断是考虑到一个类中可能有多个方法,有的方法有@Transactional注解,有的没有)

1、利用所配置的PlatformTransactionManager事务管理器新建一个数据库连接,注意TransactionManager有限制的必须是PlatformTransactionManager,然后会生成一个joinpointIdentification作为事务的名字

2、修改数据库连接的autocommit为false

3、执行MethodInvocation.proceed()方法,简单理解就是执行业务方法,其中就会执行sql

4、如果没有抛异常,则提交,执行完finally中的方法后再进行提交

5、如果抛了异常,则回滚,执行完finally中的方法后再抛出异常

Spring事务传播机制

开发过程中,经常会出现一个方法调用另外一个方法,那么就涉及到了多种场景。比如多个方法需要在同一个事务中执行;每个方法要在单独的事务中执行;有的方法需要事务,有的不需要事务;还有很多更复杂情况。Spring为了支持各种场景,也就有了Spring事务传播机制

场景分析,假设a()方法在事务执行中,调用b()方法需要开启一个新事务执行:

1、首先,代理对象执行a()方法前,先利用事务管理器新建一个数据库连接a

2、将数据库连接a的autocommit改为false

3、把数据库连接a设置到ThreadLocal中

4、执行a()方法中的sql

5、执行a()方法过程中,调用了b()方法(注意用代理对象调用b()方法)

a)代理对象执行b()方法前,判断出来了当前线程中已经存在一个数据库连接a了,表示当前线程其实已经拥有一个Spring事务了,则进行挂起

b)挂起就是把ThreadLocal中的数据库连接a从ThreadLocal中移除,并放入一个挂起资源对象中(就是事务同步管理器:TransactionSynchronizationManager)

c)挂起完成后,再次利用事务管理器新建一个数据库连接b

d)将数据库连接b的autocommit改为false

e)把数据库连接b设置到ThreadLocal中

f)执行b()方法中的sql

g)b()方法正常执行完,则从ThreadLocal中拿到数据库连接b进行提交

h)提交之后会恢复所挂起的数据库连接a,这里的恢复,其实只是把在挂起资源对象中所保存的数据库连接a再次设置到ThreadLocal中

6、a()方法正常执行完,则从ThreadLocal中拿到数据库连接a进行提交

过程核心:在执行某个方法时,判断当前是否已经存在一个事务,就是判断当前线程的ThreadLocal中是否存在一个数据库连接对象,如果存在则表示已经存在一个事务了。

代理对象执行方法时,源码invoke入口:

// TransactionInterceptor#invoke
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, new CoroutinesInvocationCallback() {
        @Override
        @Nullable
        public Object proceedWithInvocation() throws Throwable {
            // 执行后续的Interceptor,以及被代理的方法
            return invocation.proceed(); // test() sql
        }
        @Override
        public Object getTarget() {
            return invocation.getThis();
        }
        @Override
        public Object[] getArguments() {
            return invocation.getArguments();
        }
    });
}

@Override
@Nullable
public Object proceed() throws Throwable {

	// We start with an index of -1 and increment early.
	// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
	// 当调用完了最后一个interceptor后就会执行被代理方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}

	// currentInterceptorIndex初始值为-1
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

	// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
	// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		// 动态匹配,根据方法参数匹配
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			// 不匹配则执行下一个MethodInterceptor
			return proceed();
		}
	}
	else {

		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
		// 比如MethodBeforeAdviceInterceptor
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

TransactionInterceptor#invokeWithinTransaction:

/**
 * General delegate for around-advice-based subclasses, delegating to several other template
 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
 * as well as regular {@link PlatformTransactionManager} implementations and
 * {@link ReactiveTransactionManager} implementations for reactive return types.
 * @param method the Method being invoked
 * @param targetClass the target class that we're invoking the method on
 * @param invocation the callback to use for proceeding with the target invocation
 * @return the return value of the method, if any
 * @throws Throwable propagated from the target invocation
 */
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,
		final InvocationCallback invocation) throws Throwable {

	// If the transaction attribute is null, the method is non-transactional.
	// TransactionAttribute就是@Transactional中的配置
	TransactionAttributeSource tas = getTransactionAttributeSource();
	// 获取@Transactional注解中的属性值
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

	// 返回Spring容器中类型为TransactionManager的Bean对象
	final TransactionManager tm = determineTransactionManager(txAttr);

	// ReactiveTransactionManager用得少,并且它只是执行方式是响应式的,原理流程和普通的是一样的
	if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
		... ...
	}

	// 把tm强制转换为PlatformTransactionManager,所以我们在定义时得定义PlatformTransactionManager类型
	PlatformTransactionManager ptm = asPlatformTransactionManager(tm);

	// joinpoint的唯一标识,就是当前在执行的方法名字
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	// CallbackPreferringPlatformTransactionManager表示拥有回调功能的PlatformTransactionManager,也不常用
	if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
		// Standard transaction demarcation with getTransaction and commit/rollback calls.
		// 如果有必要就创建事务,这里就涉及到事务传播机制的实现了
		// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务
		TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

		Object retVal;
		try {
			// This is an around advice: Invoke the next interceptor in the chain.
			// This will normally result in a target object being invoked.
			// 执行下一个Interceptor或被代理对象中的方法
			retVal = invocation.proceedWithInvocation(); // test() sql
		}
		catch (Throwable ex) {
			// target invocation exception
			// 抛异常了,则回滚事务,或者
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			cleanupTransactionInfo(txInfo);
		}

		if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
			// Set rollback-only in case of Vavr failure matching our rollback rules...
			TransactionStatus status = txInfo.getTransactionStatus();
			if (status != null && txAttr != null) {
				retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
			}
		}

		// 提交事务
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}

	else {
		Object result;
		final ThrowableHolder throwableHolder = new ThrowableHolder();
		... ...
	}
}

/**
 * Create a transaction if necessary based on the given TransactionAttribute.
 * 

Allows callers to perform custom TransactionAttribute lookups through * the TransactionAttributeSource. * @param txAttr the TransactionAttribute (may be {@code null}) * @param joinpointIdentification the fully qualified method name * (used for monitoring and logging purposes) * @return a TransactionInfo object, whether or not a transaction was created. * The {@code hasTransaction()} method on TransactionInfo can be used to * tell if there was a transaction created. * @see #getTransactionAttributeSource() */ @SuppressWarnings("serial") protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } // 每个逻辑事务都会创建一个TransactionStatus,但是TransactionStatus中有一个属性代表当前逻辑事务底层的物理事务是不是新的 TransactionStatus status = null; if (txAttr != null) { if (tm != null) { // status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured"); } } } // 返回一个TransactionInfo对象,表示得到了一个事务,可能是新创建的一个事务,也可能是拿到的已有的事务 return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }

关键方法getTransaction(txAttr):

/**
 * This implementation handles propagation behavior. Delegates to
 * {@code doGetTransaction}, {@code isExistingTransaction}
 * and {@code doBegin}.
 * @see #doGetTransaction
 * @see #isExistingTransaction
 * @see #doBegin
 */
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
		throws TransactionException {

	// Use defaults if no transaction definition given.
	TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

	// 得到一个新的DataSourceTransactionObject对象
	// new DataSourceTransactionObject  txObject
	Object transaction = doGetTransaction();
	boolean debugEnabled = logger.isDebugEnabled();

	// transaction.getConnectionHolder().isTransactionActive()
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		return handleExistingTransaction(def, transaction, debugEnabled);
	}

	// Check definition settings for new transaction.
	if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
	}

	// No existing transaction found -> check propagation behavior to find out how to proceed.
	// 手动开启事务的传播机制
	if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	// 在当前Thread中没有事务的前提下,以下三个是等价的
	else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// 没有事务需要挂起,不过TransactionSynchronization有可能需要挂起
		// suspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
		}
		try {
			// 开启事务后,transaction中就会有数据库连接了,并且isTransactionActive为true
			// 并返回TransactionStatus对象,该对象保存了很多信息,包括被挂起的资源
			return startTransaction(def, transaction, debugEnabled, suspendedResources);
		}
		catch (RuntimeException | Error ex) {
			resume(null, suspendedResources);
			throw ex;
		}
	}
	else {
		// Create "empty" transaction: no actual transaction, but potentially synchronization.
		if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
			logger.warn("Custom isolation level specified but no actual transaction initiated; " +
					"isolation level will effectively be ignored: " + def);
		}
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
	}
}


/**
 * Create a TransactionStatus for an existing transaction.
 */
private TransactionStatus handleExistingTransaction(
		TransactionDefinition definition, Object transaction, boolean debugEnabled)
		throws TransactionException {

	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
		throw new IllegalTransactionStateException(
				"Existing transaction found for transaction marked with propagation 'never'");
	}

	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction");
		}
		// 把当前事务挂起,其中就会把数据库连接对象从ThreadLocal中移除
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(
				definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}

	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction, creating new transaction with name [" +
					definition.getName() + "]");
		}
		SuspendedResourcesHolder suspendedResources = suspend(transaction);
		try {
			return startTransaction(definition, transaction, debugEnabled, suspendedResources);
		}
		catch (RuntimeException | Error beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
	}

	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		if (!isNestedTransactionAllowed()) {
			throw new NestedTransactionNotSupportedException(
					"Transaction manager does not allow nested transactions by default - " +
					"specify 'nestedTransactionAllowed' property with value 'true'");
		}
		if (debugEnabled) {
			logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
		}
		if (useSavepointForNestedTransaction()) {
			// Create savepoint within existing Spring-managed transaction,
			// through the SavepointManager API implemented by TransactionStatus.
			// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
			DefaultTransactionStatus status =
					prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
			// 创建一个savepoint
			status.createAndHoldSavepoint();
			return status;
		}
		else {
			// Nested transaction through nested begin and commit/rollback calls.
			// Usually only for JTA: Spring synchronization might get activated here
			// in case of a pre-existing JTA transaction.
			return startTransaction(definition, transaction, debugEnabled, null);
		}
	}

	// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
	if (debugEnabled) {
		logger.debug("Participating in existing transaction");
	}
	if (isValidateExistingTransaction()) {
		if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
			Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
			if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
				Constants isoConstants = DefaultTransactionDefinition.constants;
				throw new IllegalTransactionStateException("Participating transaction with definition [" +
						definition + "] specifies isolation level which is incompatible with existing transaction: " +
						(currentIsolationLevel != null ?
								isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
								"(unknown)"));
			}
		}
		if (!definition.isReadOnly()) {
			if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
				throw new IllegalTransactionStateException("Participating transaction with definition [" +
						definition + "] is not marked as read-only but existing transaction is");
			}
		}
	}

	// 如果依然是Propagation.REQUIRED
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

开启事务startTransaction:

/**
 * Start a new transaction.
 */
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

    // 是否开启一个新的TransactionSynchronization
    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

    // 开启的这个事务的状态信息:
    // 事务的定义、用来保存数据库连接的对象、是否是新事务,是否是新的TransactionSynchronization
    DefaultTransactionStatus status = newTransactionStatus(
        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);

    // 开启事务
    doBegin(transaction, definition);

    // 如果需要新开一个TransactionSynchronization,就把新创建的事务的一些状态信息设置到TransactionSynchronizationManager中
    prepareSynchronization(status, definition);
    return status;
}

// DataSourceTransactionManager#doBegin
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;

	try {

		// 如果当前线程中所使用的DataSource还没有创建过数据库连接,就获取一个新的数据库连接
		if (!txObject.hasConnectionHolder() ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			Connection newCon = obtainDataSource().getConnection();
			if (logger.isDebugEnabled()) {
				logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
			}
			txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
		}

		txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
		con = txObject.getConnectionHolder().getConnection();

		// 根据@Transactional注解中的设置,设置Connection的readOnly与隔离级别
		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);
		txObject.setReadOnly(definition.isReadOnly());

		// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
		// so we don't want to do it unnecessarily (for example if we've explicitly
		// configured the connection pool to set it already).
		// 设置autocommit为false
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}

		prepareTransactionalConnection(con, definition);
		txObject.getConnectionHolder().setTransactionActive(true);

		// 设置数据库连接的过期时间
		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		// Bind the connection holder to the thread.
		// 把新建的数据库连接设置到resources中,resources就是一个ThreadLocal>,事务管理器中的设置的DataSource对象为key,数据库连接对象为value
		if (txObject.isNewConnectionHolder()) {
			TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
		}
	}

	catch (Throwable ex) {
		if (txObject.isNewConnectionHolder()) {
			DataSourceUtils.releaseConnection(con, obtainDataSource());
			txObject.setConnectionHolder(null, false);
		}
		throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
	}
}

Spring事务传播机制分类

以非事务方式运行:表示以非Spring事务运行,表示在执行这个方法时,Spring事务管理器不会去建立数据库连接,执行sql时,由Mybatis或JdbcTemplate自己来建立数据库连接来执行 sql。

案例分析

情况1

事务1内部调用事务2场景,无异常

@Component
public class UserService 
{
    @Autowired
    private UserService userService;
    
    @Transactional
    public void test() 
    {
        // test方法中的sql
        userService.a(); 
    }
    @Transactional
    public void a() 
    {
        // a方法中的sql
    }
}

默认情况下传播机制为REQUIRED,表示当前如果没有事务则新建一个事务,如果有事务则在当前事务中执行。

执行流程:

1、新建一个数据库连接conn

2、设置conn的autocommit为false

3、执行test方法中的sql

4、执行a方法中的sql

5、执行conn的commit()方法进行提交

情况2

事务1内部调用事务2场景,事务1内部有异常

@Component
public class UserService 
{
    @Autowired
    private UserService userService;
    
    @Transactional
    public void test() 
    {
        // test方法中的sql
        userService.a(); 
        int result = 100/0;
    }
    @Transactional
    public void a() 
    {
        // a方法中的sql
    }
}

执行流程:

1、新建一个数据库连接conn

2、设置conn的autocommit为false

3、执行test方法中的sql

4、执行a方法中的sql

5、抛出异常

6、执行conn的rollback()方法进行回滚,所以两个方法中的sql都会回滚掉

情况3

事务1内部调用事务2场景,事务2内部有异常

@Component
public class UserService 
{
    @Autowired
    private UserService userService;
    
    @Transactional
    public void test() 
    {
        // test方法中的sql
        userService.a(); 
    }
    @Transactional
    public void a() 
    {
        // a方法中的sql
        int result = 100/0;
    }
}

执行流程:

1、新建一个数据库连接conn

2、设置conn的autocommit为false

3、执行test方法中的sql

4、执行a方法中的sql

5、抛出异常

6、执行conn的rollback()方法进行回滚,所以两个方法中的sql都会回滚掉

对于事务1而言,userService.a(); 这个方法的调用抛出了异常,所以事务1也要回滚

情况4
@Component
public class UserService 
{
    @Autowired
    private UserService userService;
    
    @Transactional
    public void test() 
    {
        // test方法中的sql
        userService.a(); 
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void a() 
    {
        // a方法中的sql
        int result = 100/0;
    }
}

执行流程:

1、新建一个数据库连接conn

2、设置conn的autocommit为false

3、执行test方法中的sql

4、又新建一个数据库连接conn2

5、执行a方法中的sql

6、抛出异常

7、执行conn2的rollback()方法进行回滚

8、继续抛异常,对于test()方法而言,它会接收到一个异常,然后抛出

9、执行conn的rollback()方法进行回滚,最终还是两个方法中的sql都回滚了

Spring事务强制回滚

正常情况下,a()调用b()方法时,如果b()方法抛了异常,但是在a()方法捕获了,那么a()的事务还是会正常提交的,但是有的时候,我们捕获异常可能仅仅只是不把异常信息返回给客户端,而是为了返回一些更友好的错误信息,而这个时候,我们还是希望事务能回滚的,那这个时候就得告诉Spring把当前事务回滚掉,做法就是:

@Transactional
public void test()
{
    // 执行sql
    try 
    {
        b();
    } catch (Exception e) 
    {
        // 构造友好的错误信息返回
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

public void b() throws Exception 
{
    throw new Exception();
}

事务仍然回滚,捕获异常是为了给客户端更好的提示

TransactionSynchronization

Spring事务有可能会提交,回滚、挂起、恢复,所以Spring事务提供了一种机制,可以让程序员来监听当前Spring事务所处于的状态。

@Component
public class UserService
{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private UserService userService;
    
    @Transactional
    public void test()
    {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization()
        {
            @Override
            public void suspend()
            {
                System.out.println("test被挂起了");
            }
            
            @Override
            public void resume()
            {
                System.out.println("test被恢复了");
            }
            
            @Override
            public void beforeCommit(boolean readOnly)
            {
                System.out.println("test准备要提交了");
            }
            
            @Override
            public void beforeCompletion()
            {
                System.out.println("test准备要提交或回滚了");
            }
            
            @Override
            public void afterCommit()
            {
                System.out.println("test提交成功了");
            }
            
            @Override
            public void afterCompletion(int status)
            {
                System.out.println("test提交或回滚成功了");
            }
        });
        jdbcTemplate.execute("insert into t1 values(1,1,1,1,'1')");
        System.out.println("test");
        userService.a();
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void a()
    {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization()
        {
            @Override
            public void suspend()
            {
                System.out.println("a被挂起了");
            }
            
            @Override
            public void resume()
            {
                System.out.println("a被恢复了");
            }
            
            @Override
            public void beforeCommit(boolean readOnly)
            {
                System.out.println("a准备要提交了");
            }
            
            @Override
            public void beforeCompletion()
            {
                System.out.println("a准备要提交或回滚了");
            }
            
            @Override
            public void afterCommit()
            {
                System.out.println("a提交成功了");
            }
            
            @Override
            public void afterCompletion(int status)
            {
                System.out.println("a提交或回滚成功了");
                System.out.println("a提交或回滚成功了");
            }
        });
        jdbcTemplate.execute("insert into t1 values(2,2,2,2,'2')");
        System.out.println("a");
    }
}

你可能感兴趣的:(spring,java)