spring 事务源码(二)事务切面详细

系列文章

spring 事务源码(三)如何保证被@Transactional标记方法中的所有sql都在一个事务内

spring 事务源码(二)事务切面详细

spring 事务源码(一)事务切面注入、解析

前言

上文说到事务注解处理的切面如何注入、解析,这篇文章说下具体事务切面如何运行事务

测试代码

环境

jdk 1.8

spring boot 2.0.4

mybatis-plus-boot-starter 3.4.1

@Component
public class WebHelper {

    @Autowired
    CourseItemServiceImpl courseItemService;

    @Transactional
    public void test(){
        courseItemService.getById(1);
    }

}

源码

继上文结尾验证事务抛出堆栈异常,可以看到

在这里插入图片描述

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction


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

   
   TransactionAttributeSource tas = getTransactionAttributeSource();
  // 获取当前方法或者类上的事务注解属性
   final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
  // 获取事务管理器 
  final PlatformTransactionManager tm = determineTransactionManager(txAttr);

   final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

   if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      // 根据事务注解属性创建事务信息
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
      Object retVal = null;
      try {
         // 最终调用@Transactional 注解的方法
         retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
         // 事务执行异常处理,包含回滚操作
        // 最终调用 DataSourceTransactionManager#doRollback
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      }
      finally {
         cleanupTransactionInfo(txInfo);
      }
      // 事务提交
     // 最终调用 DataSourceTransactionManager#doCommit
      commitTransactionAfterReturning(txInfo);
      return retVal;
   }

   else {
			......
        // 事务管理器如果是CallbackPreferringPlatformTransactionManager运行此方法
      // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
      ...
     
   }
}

事务管理器获取

org.springframework.transaction.interceptor.TransactionAspectSupport#determineTransactionManager

@Nullable
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
   // 如果没有事务属性,直接返回默认事务管理器
   if (txAttr == null || this.beanFactory == null) {
      return getTransactionManager();
   }

  // 当前事务是否指定事务管理器
  //形如:@Transactional(value = "wss")
   String qualifier = txAttr.getQualifier();
   if (StringUtils.hasText(qualifier)) {
     // 从当前spring 容器中获取指定的事务管理器
      return determineQualifiedTransactionManager(this.beanFactory, qualifier);
   }
   else if (StringUtils.hasText(this.transactionManagerBeanName)) {
      // 目前不知道什么场景调用
      return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
   }
   else {
     // 大部分都是走这个
      PlatformTransactionManager defaultTransactionManager = getTransactionManager();
      if (defaultTransactionManager == null) {
         defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
         if (defaultTransactionManager == null) {
            defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
            this.transactionManagerCache.putIfAbsent(
                  DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
         }
      }
      return defaultTransactionManager;
   }
}

通过断点分析,默认的事务管理器是DataSourceTransactionManager

事务信息创建和初始化

org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
      @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

 	//.....

   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");
         }
      }
   }
  // 事务准备
  // 将事务绑定当前线程上下文
   return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

这是最核心的方法

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
  // 获取事务管理信息
   Object transaction = doGetTransaction();

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

   if (isExistingTransaction(transaction)) {
      // 如果当前线程上下文已经存在事务,则根据事务注解的隔离级别处理
      return handleExistingTransaction(definition, transaction, debugEnabled);
   }

   // 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);
     
      try {
         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        // 创建事务 TransactionStatus
         DefaultTransactionStatus status = newTransactionStatus(
               definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        // 开启事务,提交sql
         doBegin(transaction, definition);
        // TransactionSynchronizationManager 相关属性处理
        // 当前线程上下文事务属性初始化
         prepareSynchronization(status, definition);
         return status;
      }
      .....
   }
   else {
      // 创建空事务,没有实际的事务处理但是也是创建 TransactionStatus
      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);
   }
}

下面主要说下org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

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

		try {
      // 创建数据库链接
			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();

      // 事务级别
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);

			// 如果设置主动提交
			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);
			}

			// 在当前线程上下文绑定数据库链接持有信息
			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);
		}
	}

总结

现在先缕缕大致的事务切面逻辑:

1.根据当前线程上下文中的事务管理器通过注解属性值创建事务

2.将当前事务信息绑定到线程上下文中

3.事务异常根据属性值是否回滚

4.事务执行结束提交

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值