Spring系列-Spring事务处理原理分析

介绍:
Spring既支持编程式事务处理方式,又支持声明式事务处理方式。
编程式处理方式,是我们自己通过TransactionManager的commit和rollback来实现。声明式处理方式是我们比较常用的一种,可以在xml中配置,或者通过@Transactional注解方式来使用。

事务实现原理:
事务处理模块本质是通过AOP来实现的。在配置xml的时候,我们会配置TransactionProxyFactoryBean,接下来看下相关的一些类:
在这里插入图片描述
TransactionProxyFactoryBean类继承自AbstractSingletonProxyFactoryBean,AbstractSingletonProxyFactoryBean又实现了InitializingBean接口,那就看下AbstractSingletonProxyFactoryBean的afterPropertiesSet方法的实现:

@Override
public void afterPropertiesSet() {
	// target不能为空
	if (this.target == null) {
		throw new IllegalArgumentException("Property 'target' is required");
	}
	// target必须是一个bean的引用
	if (this.target instanceof String) {
		throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
	}
	if (this.proxyClassLoader == null) {
		this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
	}

	ProxyFactory proxyFactory = new ProxyFactory();

	if (this.preInterceptors != null) {
		for (Object interceptor : this.preInterceptors) {
			proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
		}
	}

	// Add the main interceptor (typically an Advisor).
	proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

	if (this.postInterceptors != null) {
		for (Object interceptor : this.postInterceptors) {
			proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
		}
	}

	proxyFactory.copyFrom(this);

	TargetSource targetSource = createTargetSource(this.target);
	proxyFactory.setTargetSource(targetSource);

	if (this.proxyInterfaces != null) {
		proxyFactory.setInterfaces(this.proxyInterfaces);
	}
	else if (!isProxyTargetClass()) {
		// Rely on AOP infrastructure to tell us what interfaces to proxy.
		proxyFactory.setInterfaces(
				ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
	}

	postProcessProxyFactory(proxyFactory);

	this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
}

这个afterPropertiesSet方法就是进行事务的AOP配置的地方,方法开始会进行一些判断,比如target不能为空,target必须是一个bean的引用等。接下来会新建一个ProxyFactory对象,配置proxyFactory的Advisor,配置目标源等操作。最后通过proxyFactory.getProxy方法,创建一个代理对象。需要注意的是在设置Advisor的时候,有个createMainInterceptor方法,注释写的是设置主要的interceptor。那就再看看这个方法,这个方法需要调用到子类TransactionProxyFactoryBean中。

private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

@Override
protected Object createMainInterceptor() {
	this.transactionInterceptor.afterPropertiesSet();
	if (this.pointcut != null) {
		return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
	}
	else {
		// Rely on default pointcut.
		return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
	}
}

这个方法会根据场景不同,返回两种Advisor,DefaultPointcutAdvisor或TransactionAttributeSourceAdvisor,并且会把transactionInterceptor设置进去。这个transactionInterceptor就是就是实现事务的拦截器。接下来再看下TransactionAttributeSourceAdvisor这个类。

public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {

	private TransactionInterceptor transactionInterceptor;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null);
		}
	};

}

这个Advisor定义了Advice是TransactionInterceptor,Pointcut是TransactionAttributeSourcePointcut,这个TransactionAttributeSourcePointcut就是判断一个调用是否需要触发事务处理的,看下TransactionAttributeSourcePointcut的实现:


@Override
public boolean matches(Method method, Class<?> targetClass) {
	if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
		return false;
	}
	TransactionAttributeSource tas = getTransactionAttributeSource();
	return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

方法中有个matches方法,用来进行条件判断。这里用到的TransactionAttributeSource是NameMatchTransactionAttributeSource,具体不再详细说明,感兴趣的可以自己研究下。

由于在AbstractSingletonProxyFactoryBean中,设置了代理类,在对方法调用时,会调用到代理类设置的拦截器,也就是TransactionInterceptor,下面看下TransactionInterceptor的实现,可以看到有invoke方法,来执行回调:

@Override
public Object invoke(final 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 InvocationCallback() {
		@Override
		public Object proceedWithInvocation() throws Throwable {
			return invocation.proceed();
		}
	});
}

这个方法,调用了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.
 * @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
 */
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
		throws Throwable {

	// If the transaction attribute is null, the method is non-transactional.
	final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
	// 根据配置信息获取具体的事务处理器
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	final String joinpointIdentification = methodIdentification(method, targetClass);

	// 不同的PlatformTransactionManager,处理逻辑不一样,区分CallbackPreferringPlatformTransactionManager类型和非CallbackPreferringPlatformTransactionManager类型的
	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// Standard transaction demarcation with getTransaction and commit/rollback calls.
		TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
		Object retVal = null;
		try {
			// This is an around advice: Invoke the next interceptor in the chain.
			// This will normally result in a target object being invoked.
			retVal = invocation.proceedWithInvocation();
		}
		catch (Throwable ex) {
			// target invocation exception
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			cleanupTransactionInfo(txInfo);
		}
		// 通过事务处理器提交事务
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}

	else {
		// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
		// 通过回调方法来使用事务处理器。
		try {
			Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
					new TransactionCallback<Object>() {
						@Override
						public Object doInTransaction(TransactionStatus status) {
							TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
							try {
								return invocation.proceedWithInvocation();
							}
							catch (Throwable ex) {
								if (txAttr.rollbackOn(ex)) {
									// A RuntimeException: will lead to a rollback.
									if (ex instanceof RuntimeException) {
										throw (RuntimeException) ex;
									}
									else {
										throw new ThrowableHolderException(ex);
									}
								}
								else {
									// A normal return value: will lead to a commit.
									return new ThrowableHolder(ex);
								}
							}
							finally {
								cleanupTransactionInfo(txInfo);
							}
						}
					});

			// Check result: It might indicate a Throwable to rethrow.
			if (result instanceof ThrowableHolder) {
				throw ((ThrowableHolder) result).getThrowable();
			}
			else {
				return result;
			}
		}
		catch (ThrowableHolderException ex) {
			throw ex.getCause();
		}
	}
}

从方法名可以看出来,这个方法调用是会有事务逻辑的。determineTransactionManager方法会根据TransactionAttribute的属性获取具体的PlatformTransactionManager。接下来,会根据PlatformTransactionManager的类型,执行不同的逻辑。因为不同类型的PlatformTransactionManager调用方式不同。对于CallbackPreferringPlatformTransactionManager来说,需要回调函数来实现事务的创建和提交,而非CallbackPreferringPlatformTransactionManager类型则不需要通过回调。
接下来对于非CallbackPreferringPlatformTransactionManager事务处理器来说,会调用createTransactionIfNecessary方法,创建事务。然后是invocation.proceedWithInvocation();方法,沿着拦截器链调用。最后通过completeTransactionAfterThrowing方法进行回滚或提交,通过commitTransactionAfterReturning来对事务进行提交。
上面这个方法就是完整的事务处理流程,只不过每个小方法中,还有一些细节,接下来对这个流程中涉及到的方法进行分析。先看下createTransactionIfNecessary方法是如何创建事务的:

/**
 * Create a transaction if necessary based on the given TransactionAttribute.
 * <p>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(
		PlatformTransactionManager tm, 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 status = null;
	if (txAttr != null) {
		if (tm != null) {
			// 创建事务,返回TransactionStatus记录当前事务状态
			status = tm.getTransaction(txAttr);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
						"] because no transaction manager has been configured");
			}
		}
	}
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

该方法一开始会判断TransactionAttribute中是否有名字,如果没有名字,则使用方法特征来作为事务名。接下来会调用PlatformTransactionManager的getTransaction方法,创建事务,并返回TransactionStatus对象,TransactionStatus封装了事务执行的状态信息。最后会调用prepareTransactionInfo,返回一个TransactionInfo对象,TransactionInfo封装了事务处理的配置信息和TransactionStatus。接下来就看下getTransaction和prepareTransactionInfo的详细流程:

/**
 * 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(TransactionDefinition definition) throws TransactionException {
	// 这个是个抽象函数,会调用到具体的事务处理器中。
	Object transaction = doGetTransaction();

	// Cache debug flag to avoid repeated checks.
	boolean debugEnabled = logger.isDebugEnabled();

	if (definition == null) {
		// Use defaults if no transaction definition given.
		definition = new DefaultTransactionDefinition();
	}

	// 检查当前线程是否已经存在事务,如果存在的话,需要根据定义的事务传播属性来处理事务的产生
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}

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

	// No existing transaction found -> check propagation behavior to find out how to proceed.
	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) {
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
		}
		try {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			// 开始事务,这里也是调用具体的事务处理器来实现
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException ex) {
			resume(null, suspendedResources);
			throw ex;
		}
		catch (Error err) {
			resume(null, suspendedResources);
			throw err;
		}
	}
	else {
		// Create "empty" transaction: no actual transaction, but potentially synchronization.
		if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
			logger.warn("Custom isolation level specified but no actual transaction initiated; " +
					"isolation level will effectively be ignored: " + definition);
		}
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
	}
}

/**
 * Prepare a TransactionInfo for the given attribute and status object.
 * @param txAttr the TransactionAttribute (may be {@code null})
 * @param joinpointIdentification the fully qualified method name
 * (used for monitoring and logging purposes)
 * @param status the TransactionStatus for the current transaction
 * @return the prepared TransactionInfo object
 */
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
		TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {

	TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
	if (txAttr != null) {
		// We need a transaction for this method
		if (logger.isTraceEnabled()) {
			logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
		}
		// The transaction manager will flag an error if an incompatible tx already exists
		txInfo.newTransactionStatus(status);
	}
	else {
		// The TransactionInfo.hasTransaction() method will return
		// false. We created it only to preserve the integrity of
		// the ThreadLocal stack maintained in this class.
		if (logger.isTraceEnabled())
			logger.trace("Don't need to create transaction for [" + joinpointIdentification +
					"]: This method isn't transactional.");
	}

	// We always bind the TransactionInfo to the thread, even if we didn't create
	// a new transaction here. This guarantees that the TransactionInfo stack
	// will be managed correctly even if no transaction was created by this aspect.
	txInfo.bindToThread();
	return txInfo;
}

在getTransaction方法中,一开始会调用doGetTransaction方法,这个doGetTransaction是个抽象函数,最终会由具体的事务处理器来实现,比如DataSourceTransactionManager。接下来还会检查当前线程是否已经存在事务,如果存在的话,还需要根据在事务属性中定义的事务传播属性来处理事务的产生。这里会涉及到事务的传播属性,感兴趣同学可以专门研究下,这里就不再详细说明。
在getTransaction方法下面,还会调用doBegin方法,开始事务。这个doBegin方法也是会调用到具体的实现类中,也就是具体的事务处理器。最后,getTransaction方法会返回一个TransactionStatus类型的对象,封装事务的执行情况。
接下来,就再看下getTransaction中的doGetTransaction方法和doBegin方法,因为这两个方法是调用到具体的事务处理器中的,所以我们就以DataSourceTransactionManager为例,看下具体的逻辑实现:

@Override
protected Object doGetTransaction() {
	DataSourceTransactionObject txObject = new DataSourceTransactionObject();
	txObject.setSavepointAllowed(isNestedTransactionAllowed());
	ConnectionHolder conHolder =
			(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
	txObject.setConnectionHolder(conHolder, false);
	return txObject;
}

这个doGetTransaction就是用来创建事务的地方,这个事务是由Connection来完成的,把Connection放入ConnectionHolder中,在封装到DataSourceTransactionObject中,吧DataSourceTransactionObject返回。

/**
 * This implementation sets the isolation level but ignores the timeout.
 */
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;

	try {
		if (txObject.getConnectionHolder() == null ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			Connection newCon = this.dataSource.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();

		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);

		// 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).
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}
		txObject.getConnectionHolder().setTransactionActive(true);

		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		// Bind the session holder to the thread.
		if (txObject.isNewConnectionHolder()) {
			TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
		}
	}

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

doBegin方法是事务开始的地方,方法中会把Connection的autoCommit属性设置为false,相当于这个事务不会自动提交。而且会调用bindResource方法,把这个Connection和当前的线程绑定。

分析到这里,事务的提交就看完了,其实这里还涉及到事务的挂起,就先不分析了。接下来再看下事务的提交和回滚的逻辑。
事务的提交和回滚,还是在invokeWithinTransaction方法中,顺着completeTransactionAfterThrowing和commitTransactionAfterReturning方法分析,就可以看到具体的实现。事务提交会调用到AbstractPlatformTransactionManager的commit方法,事务回滚会调用到AbstractPlatformTransactionManager的rollback方法。接下来就看下这两个方法:

/**
 * This implementation of commit handles participating in existing
 * transactions and programmatic rollback requests.
 * Delegates to {@code isRollbackOnly}, {@code doCommit}
 * and {@code rollback}.
 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
 * @see #doCommit
 * @see #rollback
 */
@Override
public final void commit(TransactionStatus status) throws TransactionException {
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException(
				"Transaction is already completed - do not call commit or rollback more than once per transaction");
	}

	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
	if (defStatus.isLocalRollbackOnly()) {
		if (defStatus.isDebug()) {
			logger.debug("Transactional code has requested rollback");
		}
		processRollback(defStatus);
		return;
	}
	if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
		if (defStatus.isDebug()) {
			logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
		}
		processRollback(defStatus);
		// Throw UnexpectedRollbackException only at outermost transaction boundary
		// or if explicitly asked to.
		if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
			throw new UnexpectedRollbackException(
					"Transaction rolled back because it has been marked as rollback-only");
		}
		return;
	}

	processCommit(defStatus);
}

/**
 * This implementation of rollback handles participating in existing
 * transactions. Delegates to {@code doRollback} and
 * {@code doSetRollbackOnly}.
 * @see #doRollback
 * @see #doSetRollbackOnly
 */
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException(
				"Transaction is already completed - do not call commit or rollback more than once per transaction");
	}

	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
	processRollback(defStatus);
}

在commit方法中,会对TransactionStatus进行判断,如果在事务的执行过程中发生了异常,则会调用processRollback方法进行事务回滚。如果事务正常执行完成,则调用processCommit方法进行提交。在rollback方法中,也是调用processRollback进行事务回滚。接下来,再看下processCommit和processRollback的逻辑:

/**
 * Process an actual commit.
 * Rollback-only flags have already been checked and applied.
 * @param status object representing the transaction
 * @throws TransactionException in case of commit failure
 */
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
	try {
		boolean beforeCompletionInvoked = false;
		try {
			prepareForCommit(status);
			triggerBeforeCommit(status);
			triggerBeforeCompletion(status);
			beforeCompletionInvoked = true;
			boolean globalRollbackOnly = false;
			if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
				globalRollbackOnly = status.isGlobalRollbackOnly();
			}
			if (status.hasSavepoint()) {
				if (status.isDebug()) {
					logger.debug("Releasing transaction savepoint");
				}
				status.releaseHeldSavepoint();
			}
			else if (status.isNewTransaction()) {
				if (status.isDebug()) {
					logger.debug("Initiating transaction commit");
				}
				doCommit(status);
			}
			// Throw UnexpectedRollbackException if we have a global rollback-only
			// marker but still didn't get a corresponding exception from commit.
			if (globalRollbackOnly) {
				throw new UnexpectedRollbackException(
						"Transaction silently rolled back because it has been marked as rollback-only");
			}
		}
		catch (UnexpectedRollbackException ex) {
			// can only be caused by doCommit
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
			throw ex;
		}
		catch (TransactionException ex) {
			// can only be caused by doCommit
			if (isRollbackOnCommitFailure()) {
				doRollbackOnCommitException(status, ex);
			}
			else {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
			}
			throw ex;
		}
		catch (RuntimeException ex) {
			if (!beforeCompletionInvoked) {
				triggerBeforeCompletion(status);
			}
			doRollbackOnCommitException(status, ex);
			throw ex;
		}
		catch (Error err) {
			if (!beforeCompletionInvoked) {
				triggerBeforeCompletion(status);
			}
			doRollbackOnCommitException(status, err);
			throw err;
		}

		// Trigger afterCommit callbacks, with an exception thrown there
		// propagated to callers but the transaction still considered as committed.
		try {
			triggerAfterCommit(status);
		}
		finally {
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
		}

	}
	finally {
		cleanupAfterCompletion(status);
	}
}

在processCommit中,会先执行事务提交的准备工作,然后调用doCommit方法进行提交,最后会进行一些异常的处理和清理工作。这个doCommit会调用具体的事务处理器中的方法。

/**
 * Process an actual rollback.
 * The completed flag has already been checked.
 * @param status object representing the transaction
 * @throws TransactionException in case of rollback failure
 */
private void processRollback(DefaultTransactionStatus status) {
	try {
		try {
			triggerBeforeCompletion(status);
			if (status.hasSavepoint()) {
				if (status.isDebug()) {
					logger.debug("Rolling back transaction to savepoint");
				}
				status.rollbackToHeldSavepoint();
			}
			else if (status.isNewTransaction()) {
				if (status.isDebug()) {
					logger.debug("Initiating transaction rollback");
				}
				doRollback(status);
			}
			else if (status.hasTransaction()) {
				if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
					if (status.isDebug()) {
						logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
					}
					doSetRollbackOnly(status);
				}
				else {
					if (status.isDebug()) {
						logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
					}
				}
			}
			else {
				logger.debug("Should roll back transaction but cannot - no transaction available");
			}
		}
		catch (RuntimeException ex) {
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
			throw ex;
		}
		catch (Error err) {
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
			throw err;
		}
		triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
	}
	finally {
		cleanupAfterCompletion(status);
	}
}

在processRollback中,逻辑也类似,先进行回滚前的准备工作,然后调用具体的事务处理器中的doRollback进行回滚,最后再进行一些异常的处理和清理工作。

接下来,就还是以DataSourceTransactionManager为例,看下提交和回滚的实现:

@Override
protected void doCommit(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	if (status.isDebug()) {
		logger.debug("Committing JDBC transaction on Connection [" + con + "]");
	}
	try {
		con.commit();
	}
	catch (SQLException ex) {
		throw new TransactionSystemException("Could not commit JDBC transaction", ex);
	}
}

@Override
protected void doRollback(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	if (status.isDebug()) {
		logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
	}
	try {
		con.rollback();
	}
	catch (SQLException ex) {
		throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
	}
}

这里的逻辑很简单,本质是调用Connection的commit和rollback方法,进行事务的提交和回滚。

分析到这里,整个Spring事务处理的流程就算是分析完了。总体来看,这就是一个Spring AOP的应用,通过TransactionInterceptor拦截器进行事务控制。很多逻辑都放在了AbstractPlatformTransactionManager中实现,具体和数据源相关的操作,则定义了不同的事务处理器来实现。

参考资料:
1.《Spring技术内幕》 计文柯 著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值