2024-12-18  阅读(80)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/6160921407

回答

在 Spring 中,事务的传播机制并不会在多线程环境下生效。这是因为 Spring 事务的实现是基于 ThreadLocal。一个事务上下文与单个线程绑定。所以,如果我们在一个方法里面开启一个新的线程来执行任务,这个新线程是无法继承原有事务上下文的,会导致事务隔离。

举个简单的例子,在一个主线程中开启了事务,而在这个事务过程中启动了一个新的线程,这个新线程的操作并不会受到主线程事务的控制。即使主线程事务回滚,子线程的事务依然会提交。

详解

@Transaction 为例。

我们知道 @Transaction 的底层是基于 AOP 的,而 TransactionInterceptor 则负责拦截代理对象目标方法,在前后增加事务控制的逻辑,事务方法的执行最终都会由TransactionInterceptorinvoke()拦截增强:

  public Object invoke(MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // 委托给 invokeWithinTransaction 执行
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
      @Override
      @Nullable
      public Object proceedWithInvocation() throws Throwable {
        return invocation.proceed();
      }
      @Override
      public Object getTarget() {
        return invocation.getThis();
      }
      @Override
      public Object[] getArguments() {
        return invocation.getArguments();
      }
    });
  }

委托给父类 TransactionAspectSupport 的 invokeWithinTransaction() 处理:

    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);
    // 1--获取事务管理器
    final TransactionManager tm = determineTransactionManager(txAttr);

    if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
      // 省略部分代码...
    }
      
    // 2---获取 PlatformTransactionManager,PlatformTransactionManager 是Spring 中事务管理的核心接口,它负责管理事务的创建、提交和回滚等操作
    
    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
      // 3-- 创建TransactionInfo
      TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

      Object retVal;
      try {
        // 4--调用业务方法
        retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
        // 5--发生异常,回滚事务、提交事务?
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
      }
      finally {
       // 6--清除事务
        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);
        }
      }
      
      // 7-- 提交事务
      commitTransactionAfterReturning(txInfo);
      return retVal;
    }

    else {
      // 省略很多代码
      return result;
    }
  }