Spring事务部分源码解析(一)

911 阅读4分钟

方便谈扩展,项目引用Jdbc和RabbitMQ 源码版本spring 4.3.x

从TransactionInterceptor开始

继承关系

image.png

方法总览

image.png

从方法可以看出,我们关注点放在invoke()即可

invoke方法

image.png

图中可以看出具体实现是调用父类TransactionAspectSupport的方法

TransactionAspectSupport

继承图

image.png

子类(可以发现子类不用多说了,注解开发)

image.png

方法

image.png

可以发现,该父类已经提供了很多可用的方法

需要着重关注这两个字段

// 线程隔离持有(下方会谈)
private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
			new NamedThreadLocal<TransactionInfo>("Current aspect-driven transaction");
// 事务管理器(下方会谈)
private PlatformTransactionManager transactionManager;

先不谈getter/setter,把重点放在根据命名比较核心的方法,总结如下

determineTransactionManager()
createTransactionIfNecessary()
prepareTransactionInfo()
invokeWithinTransaction()  *
commitTransactionAfterReturning()
completeTransactionAfterThrowing()

determineTransactionManager()

image.png
image.png

通过这个方法可以发现是获取事务管理器(并放入缓存)

createTransactionIfNecessary()

image.png

通过这份方法命名可以发现是如果有必要则创建一个事务. 实际内容是获取TransactionAttribute和TransactionStatus(开启事务,AbstractPlatformTransactionManager详解),然后预处理TransactionInfo

prepareTransactionInfo()

image.png

private void bindToThread() {
	// Expose current TransactionStatus, preserving any existing TransactionStatus
	// for restoration after this transaction is complete.
	this.oldTransactionInfo = transactionInfoHolder.get();
	transactionInfoHolder.set(this);
}

通过这个方法可以发现是实例化TransactionInfo(多例)并绑定至事务持有器

invokeWithinTransaction() *

  • 表示最核心方法. ps:此方法较长无法截图因此直接放代码
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, txAttr);

		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 {
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// 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.
										throwableHolder.throwable = ex;
										return null;
									}
								}
								finally {
									cleanupTransactionInfo(txInfo);
								}
							}
						});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}
		}
	}
  1. 获取TransactionAttribute(具体实现:SpringTransactionAnnotationParser.parseTransactionAnnotation())
  2. 获取事务管理器
  3. 获取事务属性描述符
  4. 如果TransactionAttribute == null 或者事务管理器非回调 1.1 获取处理后的TransactionInfo(开启事务)
  5. AOP执行代理方法 1.1 发生异常执行completeTransactionAfterThrowing(),并上抛 1.1 最终恢复当前线程旧事务(为事务嵌套预留)
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
	if (txInfo != null) {
		txInfo.restoreThreadLocalStatus();
	}
}
private void restoreThreadLocalStatus() {
	// Use stack to restore old transaction TransactionInfo.
	// Will be null if none was set.
	transactionInfoHolder.set(this.oldTransactionInfo);
}

1.1 未发生异常执行commitTransactionAfterReturning()

commitTransactionAfterReturning()

protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
		if (txInfo != null && txInfo.hasTransaction()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
						"] after exception: " + ex);
			}
			if (txInfo.transactionAttribute.rollbackOn(ex)) {
				try {
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
				catch (Error err) {
					logger.error("Application exception overridden by rollback error", ex);
					throw err;
				}
			}
			else {
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					throw ex2;
				}
				catch (Error err) {
					logger.error("Application exception overridden by commit error", ex);
					throw err;
				}
			}
		}
	}
  1. 如果TransactionInfo包含事务则执行回滚逻辑 1.1 如果属于回滚异常范围,则执行回滚 1.1 如果不属于回滚异常范围,则正常提交

completeTransactionAfterThrowing()

image.png

正常提交逻辑(ps: 同一个事务,如果A方法嵌套B方法,如果B方法抛出异常A捕获是否会走正常提交逻辑,如果走正常提交逻辑,事务最终是回滚还是提交? )

TransactionDefinition

image.png

子类(关注一下)

image.png

事务传播属性

TransactionAttribute

image.png

TransactionDefinition子类,增加rollbackOn(),定义回滚异常范围

TransactionStatus

image.png

传递事务状态

TransactionInfo

image.png

  1. 通过源码其实能够发现,事务提交回滚都是通过TransactionInfo.getTransactionManager().rollback()/commit()
  2. 通过源码能够发现,判断方法发生异常是否回滚是通过TransactionInfo.transactionAttribute.rollbackOn(ex)决定
  3. 通过transactionStatus传递事务相关信息
  4. 通过源码发现oldTransactionInfo是用来暂存当前线程上一个事务(感觉命名可能不是特别好,也可能个人理解不够深)

将流程串起来

  1. 获取方法Transaction配置(详细后续)
  2. 获取事务管理器(PlatformTransactionManager)
  3. 开启事务并绑定线程上下文(详情后续)
  4. 执行代理方法
  5. 异常回滚,正常提交并恢复上一个事务(详情后续)

总结

事务相关代码比较多.此篇只是先写一下基础的流程框架.具体实现放在下一篇文章(可能在这个地方还并不能关注到spring设计的优雅,慢慢来)