Spring事务源码(一)

前言

本文讲述当前线程无事务时,是如何创建新事务的

Spring事务的传播特性:

  • REQUIRED 如果当前线程无事务则创建事务,有事务则加入当前事务
  • SUPPORTS 如果当前线程有事务则加入当前事务,如果无事务则不创建事务,以无事务方式执行
  • MANDATORY 如果当前线程有事务则加入当前事务,如果无事务则抛出异常throw new IllegalTransactionStateException(
    “No existing transaction found for transaction marked with propagation ‘mandatory’”);
  • REQUIRES_NEW 如果当前线程有事务则挂起当前事务,然后新建立一个事务,如果无事务则创建事务
  • NOT_SUPPORTED 如果当前线程有事务则挂起当前事务,然后然后以无事务方式执行,如果无事务则以无事务方式执行
  • NEVER 如果当前线程有事务则抛出异常throw new IllegalTransactionStateException(
    “Existing transaction found for transaction marked with propagation ‘never’”);
  • NESTED 果当前线程无事务则创建事务,如果之前有事务,将作为之前事务的子事务,这个传播属性可以创建SavePoint(可以回滚的保存点)

一、ProxyTransactionManagementConfiguration

Spring事务配置的3个重要Bean:

  • TransactionAttributeSource @Transactinal注解的解析类
  • TransactionInterceptor Spring事务的处理类 也是Spring Aop中的advice,是Spring事务分析的重要类
  • BeanFactoryTransactionAttributeSourceAdvisor Spring事务的advisor
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	@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;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	@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;
	}

}

二、BeanFactoryTransactionAttributeSourceAdvisor

声明类一个TransactionAttributeSourcePointcut当作这个advisor的切面,它去判断哪些类需要Spring事务去增强

private TransactionAttributeSource transactionAttributeSource;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
	@Override
	protected TransactionAttributeSource getTransactionAttributeSource() {
		return transactionAttributeSource;
	}
};


abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
	// 在其matches方法上调用TransactionAttributeSource的getTransactionAttribute的方法
	// 基本思路是TransactionAttributeSource类里创建里一个SpringTransactionAnnotationParser,通过它调用
	// AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
				element, Transactional.class);
	// 将attributes包装成RuleBasedTransactionAttribute返回给此方法,如果不为空说明需要给目标类做代理
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
			return false;
		}
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}
}

三、TransactionInterceptor

TransactionInterceptor实现了MthodInterceptor接口,代理对象执行相应的方法时会先执行MthodInterceptor的invoke方法(其中一段流程略过,如知道AOP原理将很好理解为什么会执行到invoke方法,本篇文章着重讲解事务功能,对AOP方面调用不去阐述)

@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();
		}
	});
}

核心事务底层封装实现方法

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable {

		// If the transaction attribute is null, the method is non-transactional.
		// 通过TransactionAttributeSource解析方法上的@Transactional注解,如果方法上没有则解析类上的@Transactional注解,
		// 把注解信息封装成TransactionAttribute
		final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
		// 获取PlatformTransactionManager, 通常我们都是使用DataSourceTransactionManager
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// DataSourceTransactionManager没有实现CallbackPreferringPlatformTransactionManager
			// 所以走这一块代码
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			// 获取事务信息,并将事务信息封装成TransactionInfo
			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.
				// Spring Aop往下传递执行方法。直至执行原始方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				// 遇到异常需要如何处理事务
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 将txInfo存在旧的TransactionInfo,那么将旧的TransactionInfo放入线程变量transactionInfoHolder中
				cleanupTransactionInfo(txInfo);
			}
			// 走到这里说明没有异常,准备提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
		else {
			
		}
	}

获取事务信息的方法

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);
			}
		}
		// 将status和事务管理器、事务属性封装成TransactionInfo事务信息对象
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

核心方法获取事务状态

@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
	// 获取一个事务对象transaction,doGetTransaction源码如下
	/*
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		从线程变量里取出ConnectionHolder填充到txObject,因为是从线程变量取出来的,所以标记不是一个新的holder
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	*/
	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();
	}
	// 判断事务对象事务已经包含事务,如果已存在事务,就按已有事务的方式执行方法
	// isExistingTransaction源码如下:txObject的ConnectionHolder不为空且属于事务开始状态
	// 则可以判断当前线程已经存在事务
	/*
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
	*/
	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.
	// 如果走到这里说明当前线程无事务存在,但如果传播行为是PROPAGATION.MANDATORY(强制要求存在事务,否则抛出异常)
	// 则抛出异常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	// 如果当前线程无事务,但传播行为如下3种则需要创建
	else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			// 因为此处无事务,所以不会挂起任务事务信息,如事务同步管理器有事务同步器,仅仅保存一些线程变量到SuspendedResourcesHolder
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
		}
		try {
			// 判断是否要开启事务同步器,默认都是要的
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			// new一个status对象,把事务对象transaction,挂起的信息存进去,并标记为一个新事务
			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.
		// 其他几种传播行为(SUPPORTS、NOT_SUPPORTED、NEVER)以无事务方式运行当前方法
		// 判断是否要开启事务同步器,只有SYNCHRONIZATION_ALWAYS才开启事务同步器管理
		// SYNCHRONIZATION_ON_ACTUAL_TRANSACTION适应于只有开启真实事务环境下
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
	}
}

doBegin

打开新事务的原理:

  • dataSource的connection如果在没事务的情况下,遇到增,删,改会自动开启事务。
  • 如autoCommit设置为true,则每一个SQL修改完数据都执行完会自动执行事务commit
  • 把autoCommit设置成false,事务的提交与回滚交与Spring事务来管理,即实现了一个事务内执行多个Sql。
  • 因为connection和事务是关联的,所以持有connection,就可以当作持有当前事务,所以要把connection对象封装一下,存进线程变量中
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;
	try {
		// transaction对象不持有Connection对象时判断当前线程无事务,通过dataSource获取一个Connection
		if (!txObject.hasConnectionHolder() || 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();
		//设置当前Connection的隔离级别
		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		//记录Connection之前的隔离级别,用于执行完事务方便恢复Connection的隔离级别
		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).
		// 设置autoCommit为false,即事务由Spring事务来管理
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}
		// 目前只有设置如果当前事务属性配置的是ReadOnly时,把当前事务编程ReadOnly
		prepareTransactionalConnection(con, definition);
		// 设置当时ConnectionHolder时开启事务的
		txObject.getConnectionHolder().setTransactionActive(true);

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

		// Bind the connection holder to the thread.
		// 如果ConnectionHolder是通过dataSource得到的,就是NewConnectionHolder
		// 那么就把它放入线程变量中,方便在同一个线程里其他地方取出来判断当前线程是否有事务
		if (txObject.isNewConnectionHolder()) {
			TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
		}
	}
}

总结

  1. 事务是和Connection绑定的,判断当前线程是否有事务就是取出线程变量ConnectionHolder
  2. 创建事务是通过事务管理器的dataSource获取Connection, 并封装成ConnectionHolder放入线程变量中
  3. 创建事务只有当前线程无事务且传播行为为REQUIRED,REQUIRES_NEW,NESTED才会取创建事务
  4. 创建事务完毕后调用prepareTransactionStatus初始化事务同步管理器initSynchronization,
    并把事务名称,隔离级别放入线程变量中,方便用户注册事务同步器参与事务的生命周期方法。
  5. 事务创建成功后把事务信息对象DataSourceTransactionObject,是否新事务状态 封装成TransactionStatus
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值