# Spring Boot 声明式事务

## 1. 生效原理

### 1.1 编写测试Demo来测试事务

编写一个普通的 Service 来简单构造一个事务场景。

```java
@Service
public class DemoService {

    @Transactional(rollbackFor = Exception.class)
    public void test1() {
        System.out.println("test1 run...");
        int i = 1 / 0;
        System.out.println("test1 finish...");
    }

}
```

在启动类上标注 `@EnableTransactionManagement` 注解来启动注解事务。

```java
@EnableTransactionManagement
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        DemoService demoService = ctx.getBean(DemoService.class);
        demoService.test1();
    }

}
```

运行主启动类，发现控制台没有打印 `test1 finish...` ，并输出异常信息。

```java
test1 run...
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.example.demo.service.DemoService.test1(DemoService.java:12)
    at com.example.demo.service.DemoService$$FastClassBySpringCGLIB$$203c87bf.invoke(<generated>)
```

并且从控制台的异常信息栈中发现了**cglib**的身影，因为编写的 Service 没有接口，使用**cglib**创建的代理对象。

接下来咱来开始分析注解声明式事务的生效原理。

### 1.2 @EnableTransactionManagement

```java
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default Ordered.LOWEST_PRECEDENCE;
}
```

注解内部的定义咱暂且不关心，只记住默认使用 **PROXY** - 代理方式来增强代码即可。

`@EnableTransactionManagement` 注解上面声明了 `@Import` ，它导了一个Selector：`TransactionManagementConfigurationSelector` 。

### 1.3 TransactionManagementConfigurationSelector

咱已经很清楚， `ImportSelector` 的作用是筛选组件，返回组件的全限定类名，让IOC容器来创建这些组件。

```java
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
            default:
                return null;
        }
    }

}
```

`@EnableTransactionManagement` 注解默认使用 `PROXY` 来增强事务，那这个switch结构中就应该返回两个类的全限定类名：`AutoProxyRegistrar` 、`ProxyTransactionManagementConfiguration` ，可以看得出来，声明式事务最终起作用是上述两个组件的功能。下面咱分别来看这两个类。

### 1.4 AutoProxyRegistrar

```java
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
        for (String annoType : annoTypes) {
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
            if (candidate == null) {
                continue;
            }
            Object mode = candidate.get("mode");
            Object proxyTargetClass = candidate.get("proxyTargetClass");
            if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                Boolean.class == proxyTargetClass.getClass()) {
                candidateFound = true;
                // PROXY模式下会额外注册Bean
                if (mode == AdviceMode.PROXY) {
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                    if ((Boolean) proxyTargetClass) {
                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                        return;
                    }
                }
            }
        }
        if (!candidateFound) {
            String name = getClass().getSimpleName();
            // logger......
        }
    }

}
```

它又实现了 `ImportBeanDefinitionRegistrar` ，又是手动向IOC容器中导入组件。

注意中间部分的一个if判断：如果 `@EnableTransactionManagement` 注解中设置 `adviceMode` 为 `PROXY` （默认`PROXY`），则会利用 `AopUtils` 创建组件，并且如果 `@EnableTransactionManagement` 设置 `proxyTargetClass` 为true，则还会额外导入组件（默认为false）。下面咱看看它又向容器里注册了什么组件。

#### 1.4.1 AopUtils.registerAutoProxyCreatorIfNecessary

```java
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
                                                                 @Nullable Object source) {
    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

@Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
                                                                  @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}
```

从上面的方法一级一级向下执行，最终来到 `registerOrEscalateApcAsRequired` 方法（注意在第二层方法中传入了一个 `InfrastructureAdvisorAutoProxyCreator.class` （基础增强器自动代理创建器），可能下面就是注册这个类型的组件）。

（仔细观察一下，这种类名的命名风格分明就是AOP组件的命名诶。。。先保留这个疑问，继续往下看）

先看看它传的这个 `InfrastructureAdvisorAutoProxyCreator` 类是什么东西吧：

**1.4.1.1 InfrastructureAdvisorAutoProxyCreator**

文档注释原文翻译：

Auto-proxy creator that considers infrastructure Advisor beans only, ignoring any application-defined Advisors.

自动代理创建器，仅考虑基础结构Advisor类型的Bean，而忽略任何应用程序定义的Advisor。

注释解释的不是很清楚，咱再看看这个类的继承结构：

```java
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
            implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
```

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671971427682-de71222e-67c6-43fc-be9d-adcc6430dc06.png)

可以发现它也是个后置处理器，并且是在Bean创建前后执行的后置处理器（`InstantiationAwareBeanPostProcessor`），而且它来自 `spring-aop` 包。那既然是这样，它与之前AOP部分咱看到的思路就完全一致了（该类/父类中一定会有寻找增强器、过滤增强器，最终生成代理包装Bean为代理对象的方法）。

回到上面的 `AopUtils` 类，`registerAutoProxyCreatorIfNecessary` 方法注册了一个 `InfrastructureAdvisorAutoProxyCreator` ，跟之前咱在AOP部分看到的 `@EnableAspectJAutoProxy` 注解注册的 `AnnotationAwareAspectJAutoProxyCreator` 几乎完全一致了，那下面的方法也不用看了，思路真的完全一致。

### 1.5 ProxyTransactionManagementConfiguration

注意这个配置类还继承了父类，父类的配置也会被加载。

```java
@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());
		if (this.enableTx != null) {
			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;
	}

}
```

很明显它向IOC容器中注册了3个Bean。一个一个来看：

#### 1.5.1 transactionAdvisor：事务增强器

`BeanFactoryTransactionAttributeSourceAdvisor` 的文档注释原文翻译：

Advisor driven by a TransactionAttributeSource, used to include a transaction advice bean for methods that are transactional.

由 `TransactionAttributeSource` 驱动的增强器，用于为开启事务的Bean的方法附加事务通知。

文档注释大概是描述是它给业务方法增强事务通知，咱先放一边。注意看这个类名的最后：**Advisor** ，它是一个增强器！

看一眼这个类的继承和一些成员：

```java
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    @Nullable
    private TransactionAttributeSource transactionAttributeSource;

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

从这部分源码中可以得知非常关键的点：它是**利用切入点来增强方法** （源码中看到了**pointcut**）。源码中的**pointcut**属性的创建又要借助 `TransactionAttributeSource` 。这部分依赖关系如下：

```
Advisor → → →依赖→ → → Pointcut → → →依赖→ → → Source
```

**1.5.1.1 TransactionAttributeSourcePointcut**

通过前面AOP部分的阅读，咱也知道，所有的切入点类都会实现 `Pointcut` 接口，`TransactionAttributeSourcePointcut` 的类继承和部分源码：

```java
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

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

它实现了 `ClassFilter` 接口（`matches` 是重写的方法，源码不再展开）， `matches` 方法有两部分判断逻辑：是否为 `TransactionalProxy` 、`PlatformTransactionManager` 、`PersistenceExceptionTranslator` 的实现类，以及让 `TransactionAttributeSource` 获取事务属性看是否为空。前半部分好理解，后半部分需要借助 `TransactionAttributeSource` 来判断，正好配置类中事务增强器的下边就要创建一个 `AnnotationTransactionAttributeSource` ，那咱就继续往下看。

#### 1.5.2 AnnotationTransactionAttributeSource：注解事务配置源

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

创建出来的只是一个普通的 `AnnotationTransactionAttributeSource` 而已，它的文档注释原文翻译：

Implementation of the org.springframework.transaction.interceptor.TransactionAttributeSource interface for working with transaction metadata in JDK 1.5+ annotation format. This class reads Spring's JDK 1.5+ Transactional annotation and exposes corresponding transaction attributes to Spring's transaction infrastructure. Also supports JTA 1.2's javax.transaction.Transactional and EJB3's javax.ejb.TransactionAttribute annotation (if present). This class may also serve as base class for a custom TransactionAttributeSource, or get customized through TransactionAnnotationParser strategies.

org.springframework.transaction.interceptor.TransactionAttributeSource接口的实现，用于处理JDK 1.5+注释格式的事务元数据。

此类读取Spring的 `@Transactional` 注解，并将相应的事务属性公开给Spring的事务基础结构。此外，还支持JTA 1.2的 `javax.transaction.Transactional` 和EJB3的 `javax.ejb.TransactionAttribute` 注解（如果存在）。此类也可用作自定义 `TransactionAttributeSource` 的基类，或通过 `TransactionAnnotationParser` 策略进行自定义。

说了这么多，我们只关心一句话：它读取 `@Transactional` 注解。由此可见 `AnnotationTransactionAttributeSource` 是读取 `@Transactional` 注解的。

上面的Bean在创建时直接调了构造方法，这个构造方法咱还是要看一下的：

```java
public AnnotationTransactionAttributeSource() {
    this(true);
}

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
    this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet<>(2);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
    this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
    this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
```

注意下面重载的构造方法中，它给 `annotationParsers` 中添加了一个 `SpringTransactionAnnotationParser` 。

**1.5.2.1 SpringTransactionAnnotationParser**

```java
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

    @Override
    @Nullable
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
        // 搜索被标注的元素（类、方法）上是否最终标注了@Transactional注解
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
            ae, Transactional.class, false, false);
        if (attributes != null) {
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }

    public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
        return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
    }

    protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        // 解析事务传播行为
        Propagation propagation = attributes.getEnum("propagation");
        rbta.setPropagationBehavior(propagation.value());
        // 解析事务隔离级别
        Isolation isolation = attributes.getEnum("isolation");
        rbta.setIsolationLevel(isolation.value());
        // 解析超时
        rbta.setTimeout(attributes.getNumber("timeout").intValue());
        // 解析只读事务
        rbta.setReadOnly(attributes.getBoolean("readOnly"));
        rbta.setQualifier(attributes.getString("value"));
        ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();
        // 解析回滚异常
        Class<?>[] rbf = attributes.getClassArray("rollbackFor");
        for (Class<?> rbRule : rbf) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        String[] rbfc = attributes.getStringArray("rollbackForClassName");
        for (String rbRule : rbfc) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        // 解析不回滚异常的“白名单”
        Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
        for (Class<?> rbRule : nrbf) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
        for (String rbRule : nrbfc) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        rbta.getRollbackRules().addAll(rollBackRules);
        return rbta;
    }
}
```

这里面的核心方法如上述源码，可以发现它的核心功能是**解析** `**@Transactional**` **注解的信息**！

至此上面的配置类中需要的事务增强器、事务切入点、事务配置源、事务注解解析器都解析完，回到配置类中，还有一个拦截器：

#### 1.5.3 TransactionInterceptor

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

在Bean的创建过程中，它也把事务配置源保存起来了，并且还注入了事务管理器。而 `TransactionInterceptor` 本身的类定义：

```java
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable
```

发现它实现了 `MethodInterceptor` ！它也是一个AOP的增强器。那它的核心作用大概率就是控制事务咯？咱先不着急，它的工作原理咱到下一篇再看，本篇先把需要配置的组件都解析完。

***

`ProxyTransactionManagementConfiguration` 的配置读完之后，别忘了它还继承了一个父类，下面咱看看这个父类里都干了什么：

### 1.6 AbstractTransactionManagementConfiguration的配置

```java
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

    @Nullable
    protected AnnotationAttributes enableTx;

    @Nullable
    protected PlatformTransactionManager txManager;


    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        this.enableTx = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
        if (this.enableTx == null) {
            throw new IllegalArgumentException(
                    "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
        }
    }

    @Autowired(required = false)
    void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
        if (CollectionUtils.isEmpty(configurers)) {
            return;
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
        }
        TransactionManagementConfigurer configurer = configurers.iterator().next();
        this.txManager = configurer.annotationDrivenTransactionManager();
    }


    @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
        return new TransactionalEventListenerFactory();
    }

}
```

可以发现在最底下它又创建了一个组件，类型是 `TransactionalEventListenerFactory` 。

#### 1.6.1 TransactionalEventListenerFactory

它的文档注释原文翻译：

EventListenerFactory implementation that handles TransactionalEventListener annotated methods.

EventListenerFactory的实现类，用于处理带有 `@TransactionalEventListener` 注解的方法。

发现它又提到了一个注解：`@TransactionalEventListener` ，实际上 `TransactionalEventListenerFactory` 这个组件是做事务监听机制的。

【如果小伙伴还不是很了解 `@TransactionalEventListener` ，请继续往下看，熟悉的小伙伴请跳过6.1节】

**1.6.1.1 【扩展】@TransactionalEventListener**

自 SpringFramework4.2 之后，出现了一种能在事务动作发生前后注入监听器的机制。

举几个应用场景的例子：

* 执行完数据库操作后发送消息
* 执行数据库操作之前记录日志
* 业务逻辑出错时事务回滚之后发邮件警报

类似于这种事务动作执行前后进行附加操作的问题，在SpringFramework4.2之后就可以通过 `@TransactionalEventListener` 注解来实现。

`@TransactionalEventListener` 可提供4种监听时机，来执行附加操作：

* BEFORE\_COMMIT：提交之前
* AFTER\_COMMIT：提交之后
* AFTER\_ROLLBACK：回滚之后
* AFTER\_COMPLETION：事务完成之后

**1.6.1.2 @TransactionalEventListener的使用方式简单Demo**

```java
@Service
public class DemoService {

    @Autowired
    private USerDao userDao;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Transactional(rollbackFor = Exception.class)
    public void test() {
        // 执行清空用户的数据库操作
        userDao.deleteAll();

        // 使用事件广播器来广播 用户清除事件
        applicationEventPublisher.publishEvent(new UserCleanEvent());
    }
}

@Component
class MyTransactionListener {

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    private void onTestEvent(UserCleanEvent event) {
        System.out.println("UserCleanEvent detected ......");
    }

}

// 定义 用户清除事件，它需要继承ApplicationEvent 
class UserCleanEvent extends ApplicationEvent {

}
```

### 1.7 小结

1. Spring的注解事务底层是借助AOP的机制，创建了一个 `InfrastructureAdvisorAutoProxyCreator` 组件来创建代理对象。
2. 注解事务要想生效，需要**事务增强器、事务切入点解析器、事务配置源、事务拦截器**等组件。

## 2. 工作原理

### 2.0 测试Demo

```java
@Service
public class DemoService {

    @Transactional(rollbackFor = Exception.class)
    public void test1() {
        System.out.println("test1 run...");
        int i = 1 / 0;
        System.out.println("test1 finish...");
    }

}
```

被 `@Transactional` 标注的注解所在类，在IOC容器初始化时被动态代理为一个代理对象。由于上面定义的Service是类，其代理方式为**cglib**代理。故加事务的方法在执行时首先被调用的方法是：`intercept` 。

下面将以Debug步骤来逐步观察和分析事务控制流程。

### 2.1 intercept

```java
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    // ......
    try {
        // ......
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        Object retVal;
        // ......
        retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        // ......
    }
```

整个方法在之前的AOP部分分析过了，关键的步骤是上述源码中的两步：获取拦截器调用链，执行代理+目标方法的调用。

第一步获取拦截器链的内容过程咱就不看了，前面AOP部分已经分析过了，咱看下返回的拦截器都有什么：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671972699822-458b701f-ca2a-4af9-92b8-1a2f699db445.png)

只有一个拦截器，而且恰好是上一篇分析的 `TransactionInterceptor` 。

下面进入proceed方法。

### 2.2 proceed

```kotlin
public Object proceed() throws Throwable {
    //  We start with an index of -1 and increment early.
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // ......
    }
    else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
```

第一次进入 `proceed` 方法，由于此时 `-1 ≠ (1 - 1)` ，第一个if结构不进入。

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671972778191-c1e7ac12-4966-4b45-9949-195ebc7dcf0b.png)

自然进入下面的拦截器执行部分， `TransactionInterceptor` 不属于 `InterceptorAndDynamicMethodMatcher` ，自然走下面的else结构，执行 `invoke` 方法。

### 2.3 invoke

来到 `TransactionInterceptor` ：

```java
public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be 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, invocation::proceed);
}
```

首先做一次目标方法执行的空校验，`AopUtils.getTargetClass()` 是为了获取被代理的目标类，之后执行 `invokeWithinTransaction` 方法，套用事务。

### 2.4 invokeWithinTransaction

该方法在父类 `TransactionAspectSupport` 中定义。

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

    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
    // 获取@Transactional的属性配置
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    // 获取事务管理器（IOC容器中获取）
    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;
        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 {
        // 与上面相似，省略。。。
    }
}
```

由源码可以很明显看出来，它使用的是**环绕通知**。

下面的 `try-catch-finally` 中，可以发现方法正常执行后，没有问题，会在finally块下面执行 `commitTransactionAfterReturning` 方法来提交事务，出现异常时会进入catch块，执行 `completeTransactionAfterThrowing` 方法来回滚事务。

下面根据不同情况来分别Debug看效果。

#### 2.4.1 成功提交事务

将DemoService的test方法中去掉除零运算，Debug运行之后一切正常，try块没有抛出异常，进入下面的 `commitTransactionAfterReturning` 方法：

```java
try {
    retVal = invocation.proceedWithInvocation();
}
// ......
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
```

准备进入 `commitTransactionAfterReturning` 方法时的Debug状态：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671972899023-30405001-8f94-40c0-8d1a-2c1eab190392.png)

下面进入 `commitTransactionAfterReturning` 方法：

**2.4.1.1 commitTransactionAfterReturning**

```java
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
    if (txInfo != null && txInfo.getTransactionStatus() != null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
        }
        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    }
}
```

核心方法很简单：拿到事务管理器，执行 **commit** 。

**2.4.1.2 commit**

```java
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, false);
        return;
    }

    if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
        }
        processRollback(defStatus, true);
        return;
    }

    // 没有异常标记，提交事务
    processCommit(defStatus);
}
```

**2.4.1.3 processCommit**

```java
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        boolean beforeCompletionInvoked = false;

        try {
            boolean unexpectedRollback = false;
            prepareForCommit(status);
            triggerBeforeCommit(status);
            triggerBeforeCompletion(status);
            beforeCompletionInvoked = true;

            // 是否有保存点
            if (status.hasSavepoint()) {
                if (status.isDebug()) {
                    logger.debug("Releasing transaction savepoint");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
                // 保存点不会真正提交事务
                status.releaseHeldSavepoint();
            }
                // 全新的事务会执行commit操作（与事务传播行为有关）
            else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction commit");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
                doCommit(status);
            }
            else if (isFailEarlyOnGlobalRollbackOnly()) {
                unexpectedRollback = status.isGlobalRollbackOnly();
            }

            // Throw UnexpectedRollbackException if we have a global rollback-only
            // marker but still didn't get a corresponding exception from commit.
            if (unexpectedRollback) {
                throw new UnexpectedRollbackException(
                    "Transaction silently rolled back because it has been marked as rollback-only");
            }
        }
        // catch ......

    }
    finally {
        // 清除缓存资源
        cleanupAfterCompletion(status);
    }
}
```

由于当前测试的Demo仅仅是单方法事务，所以它是一个全新的事务，进入else-if块，执行 `**doCommit**` 方法。（又看到xxx和doXXX了）

**2.4.1.4 doCommit**

```java
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);
    }
}
```

至此发现了我们熟悉的面孔，这也是jdbc最底层的API：拿 `Connection` 对象，调用 `**commit**` 方法，事务成功提交。

#### 2.4.2 失败回滚事务

将DemoService的test方法中加入除零运算，Debug运行之后发现出现异常，进入 `invokeWithinTransaction` 方法中的 catch 块：

```java
try {
    retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
    completeTransactionAfterThrowing(txInfo, ex);
    throw ex;
}
```

准备进入 `completeTransactionAfterThrowing` 方法时的Debug状态：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671973140167-f7dd974e-c4c6-4ca6-bae3-93bd25e49c60.png)

下面进入 `completeTransactionAfterThrowing` 方法：

**2.4.2.1 completeTransactionAfterThrowing**

```java
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
    // 回滚必须要保证当前正在一个事务中
    if (txInfo != null && txInfo.getTransactionStatus() != null) {
    if (logger.isTraceEnabled()) {
        logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                     "] after exception: " + ex);
    }
    // 4.2.1.1 回滚的事务必须为RuntimeException或Error类型
    if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
        try {
            // 回滚事务
            txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
        }
        // catch ......
    }
    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 ......
    }
}
}
```

在回滚之前，它要判定抛出的异常类型。

**2.4.2.1.1 rollbackOn**

```java
public boolean rollbackOn(Throwable ex) {
    return (ex instanceof RuntimeException || ex instanceof Error);
}
```

可以发现它是校验异常的类型是否为 `RuntimeException` 或 `Error` 。

判断完成后，回到 `completeTransactionAfterThrowing` 方法，它要拿事务管理器来调 `rollback` 方法。

**2.4.2.2 rollback**

```java
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, false);
}
```

方法中先校验一下事务是否已经完成，之后会执行 `processRollback` 方法。

**2.4.2.3 processRollback**

```java
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
    try {
        boolean unexpectedRollback = unexpected;

        try {
            triggerBeforeCompletion(status);

            // 如果事务状态中发现了保存点，证明当前事务是NESTD类型（子事务），会回滚到保存点
            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);
            }
            // ......
        }
        finally {
            // 清除事务缓存
            cleanupAfterCompletion(status);
        }
    }
```

测试Demo依然是单事务，进入 `doRollback` ：

**2.4.2.4 doRollback**

```java
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);
    }
}
```

又发现了我们熟悉的jdbc操作：拿 `Connection` 对象，调用 `**rollback**` 方法，事务成功回滚。

### 2.5 小结

1. 声明式事务由动态代理进入，核心方法是 `invokeWithinTransaction` 。
2. 事务管理器的提交和回滚最终是调用jdbc的底层API来进行提交和回滚。

## 3. 事务传播行为原理

前面的两篇咱们看了声明式事务的生效原理和工作原理，咱们也知道Spring有7种事务传播行为，这个在开发中也是可能会遇到的。本篇和下一篇会解析声明式事务的事务传播行为原理。

事务传播行为的7种类型：

| 事务传播行为                      | 描述                                                                            |
| --------------------------- | ----------------------------------------------------------------------------- |
| PROPAGATION\_REQUIRED       | 【默认值：必需】当前方法必须在事务中运行，如果当前线程中没有事务，则开启一个新的事务；如果当前线程中已经存在事务，则方法将会在该事务中运行。        |
| PROPAGATION\_SUPPORTS       | 【支持】当前方法单独运行时不需要事务，但如果当前线程中存在事务时，方法会在事务中运行                                    |
| PROPAGATION\_MANDATORY      | 【强制】当前方法必须在事务中运行，如果当前线程中不存在事务，则抛出异常                                           |
| PROPAGATION\_REQUIRES\_NEW  | 【新事务】当前方法必须在独立的事务中运行，如果当前线程中已经存在事务，则将该事务挂起，重新开启一个事务，直到方法运行结束再释放之前的事务          |
| PROPAGATION\_NOT\_SUPPORTED | 【不支持】当前方法不会在事务中运行，如果当前线程中存在事务，则将事务挂起，直到方法运行结束                                 |
| PROPAGATION\_NEVER          | 【不允许】当前方法不允许在事务中运行，如果当前线程中存在事务，则抛出异常                                          |
| PROPAGATION\_NESTED         | 【嵌套】当前方法必须在事务中运行，如果当前线程中存在事务，则将该事务标注保存点，形成嵌套事务。嵌套事务中的子事务出现异常不会影响到父事务保存点之前的操作。 |

## 3.0 修改测试Demo

修改测试代码如下：

```java
@Service
public class DemoService {
    
    @Transactional(rollbackFor = Exception.class)
    public void test1() {
        System.out.println("test1 run...");
        int i = 1 / 0;
        System.out.println("test1 finish...");
    }
    
}

@Service
public class DemoService2 {
    
    @Autowired
    private DemoService demoService;
    
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test2() {
        System.out.println("test2 run...");
        demoService.test1();
        System.out.println("test2 finish...");
    }
    
}

@EnableTransactionManagement
@SpringBootApplication
public class DemoApplication {
    
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        DemoService2 demoService2 = ctx.getBean(DemoService2.class);
        demoService2.test2();
    }
    
}
```

默认情况下，SpringFramework 中 `@Transactional` 的事务传播行为是 `Propagation.REQUIRED`：

Support a current transaction, create a new one if none exists.

支持当前事务，如果不存在则创建新事务。

在上面的测试代码中，应不会打印 `"test2 finish..."` 。

这其中的工作机制要回到 `invokeWithinTransaction` 方法中的 `createTransactionIfNecessary` 方法中，这部分会真正的开启事务。

下面咱还是以Debug的方式来分步调试，观察事务的开启时机：

### 3.1 【REQUIRED】第一次Debug

#### 3.1.1 invokeWithinTransaction

咱们只关注关键部分：

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

    // If the transaction attribute is null, the method is non-transactional.
    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)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        // 1.2 如果当前执行方法需要事务，则开启事务
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

        Object retVal;
        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;
    }
    // ......
}
```

`createTransactionIfNecessary` 方法会根据切入点判断是否需要开启事务，而切入点就是要执行的 `test2` 方法。

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671973855799-aeba7933-79f7-4c68-b4ed-45eca8ef07dd.png)

#### 3.1.2 createTransactionIfNecessary

```java
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
                                                       @Nullable 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) {
            // 1.3 获取事务状态。
            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);
}
```

上面先指定了当前事务的名称，下面会获取事务状态，而这个事务状态要从 `DataSourceTransactionManager` 中获取。

#### 3.1.3 getTransaction

```java
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    // 获取/创建事务对象
    Object transaction = doGetTransaction();

// log ......

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

// ......
}
```

第一个 `definition` 的判断是否为空，Debug发现它不为null，经过方法调用栈的追溯，发现它来自 `invokeWithinTransaction` 方法：

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

    // If the transaction attribute is null, the method is non-transactional.
    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)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
```

好吧，我们之前没有抓到这个点，那我们来重新Debug。

### 3.2 【REQUIRED】第二次Debug

把断点打在 `tas.getTransactionAttribute` 上，重新Debug，并进入到这个方法，发现来到了 `AbstractFallbackTransactionAttributeSource` 中。

```kotlin
private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }

    // First, see if we have a cached value.
    Object cacheKey = getCacheKey(method, targetClass);
    // 这里取出来的 cached 不是null
    TransactionAttribute cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
            return null;
        }
        else {
            return cached;
        }
    }
    else {
        // We need to work it out.
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        // Put it in the cache.
        if (txAttr == null) {
            this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
        }
        else {
            String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
            if (txAttr instanceof DefaultTransactionAttribute) {
                ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
            }
            this.attributeCache.put(cacheKey, txAttr);
        }
        return txAttr;
    }
}
```

在这个类中，`attributeCache` 是一个 **Map** 。通过Debug，走到 `this.attributeCache.get(cacheKey)` 这一句时发现返回值不为null，直接返回走了！在咱看来这个方法是第一次执行，而且是我在主启动类里手动调用的，为什么 `attributeCache` 里会有缓存呢？

注意观察上面方法中的else部分，有对 `attributeCache` 的 **put** 操作，由此大概可以断定是之前有执行过这个方法，当时 `attributeCache` 中还没有，才进入到else中，对 `attributeCache` 执行 put 操作。

我们把断点打在else中的第一行，再次Debug。

### 3.3 【REQUIRED】第三次Debug

在 `getTransactionAttribute` 的else结构中追踪，发现在IOC容器启动时就已经执行进来了。而执行该方法的调用栈中发现了一个方法：

```
**org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization**
```

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671974048823-22d39ecb-362f-4a8f-b22f-3bb3e834f4f0.png)

而且往上看还看到了 `wrapIfNecessary` ，证明这是**在AOP部分就已经触发了事务信息的加载**。

仔细看这部分的方法调用，咱会发现这部分其实它想找一些可以应用在当前创建Bean的增强器。

往上倒一级，看 `TransactionAttributeSourcePointcut` 的 `matches` 方法：

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

发现它在这里来触发加载事务定义信息的。（其实在第21篇的5.1.1节已经介绍过它了，不再赘述）

那咱大概就知道了它的触发时机了：因为在之前**开启注解事务**时，**触发自动配置**，而**自动配置中注入了一个** `**InfrastructureAdvisorAutoProxyCreator**` ，它**配合** `**BeanFactoryTransactionAttributeSourceAdvisor**` **（事务增强器）来完成事务织入**，在**第一次事务织入时要获取所有切入点**，之后它会**搜索所有切入点，判断创建的Bean是否可以被织入事务通知** ，在**搜索时**刚好来到这里要**解析事务定义信息**，所以会触发解析和缓存动作。

#### 3.3.1 继续往下走，回到getTransaction

```java
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    Object transaction = doGetTransaction();

// log ......

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

// 3.2 判断当前线程中是否存在事务
if (isExistingTransaction(transaction)) {
    // Existing transaction found -> check propagation behavior to find out how to behave.
    return handleExistingTransaction(definition, transaction, debugEnabled);
}

// ......
}
```

确定事务定义信息不为空后，下一步要调用 `isExistingTransaction` ，判断当前线程中是否存在事务。

#### 3.3.2 isExistingTransaction

来到 `DataSourceTransactionManager` ：

```java
protected boolean isExistingTransaction(Object transaction) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
```

从return的结构中看出，如果 `ConnectionHolder` 存在且激活，就表明当前线程已经存在事务。

通过Debug，发现 `ConnectionHolder` 为null，这个方法返回false，不进入上面的片段。

**3.3.2.1 ConnectionHolder**

文档注释原文翻译：

Resource holder wrapping a JDBC Connection. DataSourceTransactionManager binds instances of this class to the thread, for a specific javax.sql.DataSource. Inherits rollback-only support for nested JDBC transactions and reference count functionality from the base class. Note: This is an SPI class, not intended to be used by applications.

包装JDBC连接的资源持有者。对于特定的 `javax.sql.DataSource`，`DataSourceTransactionManager` 将此类的实例绑定到线程。

从父类继承对嵌套JDBC事务和引用计数功能的仅回滚支持。

注意：这是SPI类，不适合应用程序使用。

文档注释很容易理解，它是持有jdbc的 `Connection` 对象的，`DataSource` 、`DataSourceTransactionManager` 可以借助它实现线程绑定。

#### 3.3.3 判断超时和事务传播行为类型

```java
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    // ......
    // 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) {
    // ......
}
```

这部分先判断超时时间的设置是否合理（默认的 `TransactionDefinition.TIMEOUT_DEFAULT = -1`），之后下面要筛选事务传播行为类型：

* 如果是**MANDATORY**类型，则直接抛出异常，因为此时还没有事务
* 如果是**REQUIRED**、**REQUIRES\_NEW**、**NESTED**类型，则创建一个新的事务
* 其余情况，返回空事务

下面咱先以**REQUIRED**行为来继续Debug，看它的处理方式。

#### 3.3.4 【REQUIRED】进入else if结构

```java
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 | Error ex) {
    resume(null, suspendedResources);
    throw ex;
}
```

这里面执行了几个关键的步骤：

* 挂起null（相当于无操作）
* 创建一个新的事务状态，并标记为新事务【关键】
* 开启事务连接【关键】
* 准备事务同步工作

分步骤来看：

**3.3.4.1 suspend(null)**

```java
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
    if (TransactionSynchronizationManager.isSynchronizationActive()) {
        List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
        try {
            Object suspendedResources = null;
            if (transaction != null) {
                suspendedResources = doSuspend(transaction);
            }
            String name = TransactionSynchronizationManager.getCurrentTransactionName();
            TransactionSynchronizationManager.setCurrentTransactionName(null);
            boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
            TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
            Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
            boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
            TransactionSynchronizationManager.setActualTransactionActive(false);
            return new SuspendedResourcesHolder(
                    suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
        }
        catch (RuntimeException | Error ex) {
            // doSuspend failed - original transaction is still active...
            doResumeSynchronization(suspendedSynchronizations);
            throw ex;
        }
    }
    else if (transaction != null) {
        // Transaction active but no synchronization active.
        Object suspendedResources = doSuspend(transaction);
        return new SuspendedResourcesHolder(suspendedResources);
    }
    else {
        // Neither transaction nor synchronization active.
        return null;
    }
}
```

这个方法既然是挂起和恢复的，从这段实现中只有一个点是我们应该关注的：`doSuspend` 。

**3.3.4.1.1 doSuspend**

```java
protected Object doSuspend(Object transaction) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
```

这个方法的逻辑比较简单，它会获取上一次事务的数据源连接对象，并将其从当前 `ThreadLocal` 中移除。这里面获取数据源的部分很简单：

```java
protected DataSource obtainDataSource() {
    DataSource dataSource = getDataSource();
    Assert.state(dataSource != null, "No DataSource set");
    return dataSource;
}
```

关键的部分在 `TransactionSynchronizationManager.unbindResource` 中：

**3.3.4.1.2 TransactionSynchronizationManager.unbindResource**

```java
public static Object unbindResource(Object key) throws IllegalStateException {
    Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
    Object value = doUnbindResource(actualKey);
    if (value == null) {
        throw new IllegalStateException(
            "No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
    }
    return value;
}
```

又看到了doXXX，进到 `doUnbindResource` 中：

**3.3.4.1.3 doUnbindResource**

```java
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");

private static Object doUnbindResource(Object actualKey) {
    Map<Object, Object> map = resources.get();
if (map == null) {
    return null;
}
Object value = map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
    resources.remove();
}
// Transparently suppress a ResourceHolder that was marked as void...
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
    value = null;
}
if (value != null && logger.isTraceEnabled()) {
    logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
                 Thread.currentThread().getName() + "]");
}
return value;
}
```

可以看到它对 `ThreadLocal` 中的事务对象进行移除操作，完成事务解除绑定。

至此，`suspend(null)` 执行完毕。

**3.3.4.2 newTransactionStatus**

注意源码中传入构造方法中的参数 `newTransaction` ：true （第三个参数），标明马上要开启一个**新事务**。

```java
DefaultTransactionStatus status = newTransactionStatus(
    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);

protected DefaultTransactionStatus newTransactionStatus(
    TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
    boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

    boolean actualNewSynchronization = newSynchronization &&
        !TransactionSynchronizationManager.isSynchronizationActive();
    return new DefaultTransactionStatus(
        transaction, newTransaction, actualNewSynchronization,
        definition.isReadOnly(), debug, suspendedResources);
}
```

**3.3.4.3 doBegin**

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

    try {
        // 如果当前线程中没有ConnectionHolder，则会获取新的数据库连接，并放入ConnectionHolder（线程绑定）
        if (!txObject.hasConnectionHolder() ||
            txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            // 从DataSource中取connection
            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);

        // 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);
        }

        prepareTransactionalConnection(con, definition);
        // 标记事务状态为激活
        txObject.getConnectionHolder().setTransactionActive(true);

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

        // Bind the connection holder to the thread.
        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);
    }
}
```

try块中的第一个if结构体中，看到了 `obtainDataSource().getConnection()` ，获取到真正的数据库连接。

之后下面的if结构中，发现了 `con.setAutoCommit(false)` ，表明关闭自动提交，即**开启事务**。

**3.3.4.4 prepareSynchronization**

```java
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
    if (status.isNewSynchronization()) {
        TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
        TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
            definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
            definition.getIsolationLevel() : null);
        TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
        TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
        TransactionSynchronizationManager.initSynchronization();
    }
}
```

这部分是将事务状态和事务定义信息放入事务同步管理器中，逻辑很简单，不再展开。

#### 3.3.5 回到createTransactionIfNecessary

```java
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);
        }
        // ......
    }
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
```

最后一步准备事务信息：

#### 3.3.6 prepareTransactionInfo

```java
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
                                                 @Nullable TransactionAttribute txAttr, String joinpointIdentification,
                                                 @Nullable 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("No need to create transaction for [" + joinpointIdentification +
                         "]: This method is not 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;
}
```

中间大段的日志打印就不看了，最后有一个 `txInfo.bindToThread()` ：

#### 3.3.7 txInfo.bindToThread()

```java
private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
    new NamedThreadLocal<>("Current aspect-driven transaction");

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

可以发现又是直接把当前的事务信息放入 `ThreadLocal` 中。

至此，`createTransactionIfNecessary` 方法执行完成，`DemoService2` 的事务成功创建。

### 3.4 【REQUIRED】DemoService2执行DemoService

```java
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test2() {
    System.out.println("test2 run...");
    demoService.test1();
    System.out.println("test2 finish...");
}
```

当 `DemoService2` 的 `test2` 执行中，会执行 `DemoService` 的 `test1` 方法。

此时又会触发开启事务，来到 `invokeWithinTransaction` 方法：

#### 3.4.1 invokeWithinTransaction

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

    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

        // ......
    }
    // ......
}
```

再次进入 `createTransactionIfNecessary` 方法：

#### 3.4.2 createTransactionIfNecessary

```java
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);
        }
        // ......
    }
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
```

进入 `getTransaction` ：

#### 3.4.3 getTransaction

```java
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    Object transaction = doGetTransaction();

// ......

if (isExistingTransaction(transaction)) {
    // Existing transaction found -> check propagation behavior to find out how to behave.
    return handleExistingTransaction(definition, transaction, debugEnabled);
}
```

首先去获取事务：

```java
protected Object doGetTransaction() {
    DataSourceTransactionObject txObject = new DataSourceTransactionObject();
    txObject.setSavepointAllowed(isNestedTransactionAllowed());
    // 由于之前已经在ThreadLocal中放入DemoService2的事务，此时可以去除
    ConnectionHolder conHolder =
        (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
    txObject.setConnectionHolder(conHolder, false);
    return txObject;
}
```

之后去下面的 `isExistingTransaction` 方法，很明显此时已经存在事务，进入 `handleExistingTransaction` 方法。

#### 3.4.4 handleExistingTransaction

```java
private TransactionStatus handleExistingTransaction(
    TransactionDefinition definition, Object transaction, boolean debugEnabled)
    throws TransactionException {

    // 如果当前方法的事务行为是NEVER（不允许），则抛出异常
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
        throw new IllegalTransactionStateException(
            "Existing transaction found for transaction marked with propagation 'never'");
    }

    // 如果当前方法的事务行为是NOT_SUPPORTED，挂起当前事务，执行完成之后，再次唤醒
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction");
        }
        Object suspendedResources = suspend(transaction);
        boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        return prepareTransactionStatus(
            definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    }

    // 如果当前方法的事务行为是REQUIRED_NEW,挂起当前事务，并新建一个事务执行，执行完之后，唤醒上个事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction, creating new transaction with name [" +
                         definition.getName() + "]");
        }
        SuspendedResourcesHolder suspendedResources = suspend(transaction);
        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 | Error beginEx) {
            resumeAfterBeginException(transaction, suspendedResources, beginEx);
            throw beginEx;
        }
    }

    // 如果当前方法的事务行为是NESTED，创建一个保存点
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
        if (!isNestedTransactionAllowed()) {
            throw new NestedTransactionNotSupportedException(
                "Transaction manager does not allow nested transactions by default - " +
                "specify 'nestedTransactionAllowed' property with value 'true'");
        }
        if (debugEnabled) {
            logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
        }
        if (useSavepointForNestedTransaction()) {
            // Create savepoint within existing Spring-managed transaction,
            // through the SavepointManager API implemented by TransactionStatus.
            // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
            DefaultTransactionStatus status =
                prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
                                         status.createAndHoldSavepoint();
                                         return status;
                                         }
                                         else {
                                         // Nested transaction through nested begin and commit/rollback calls.
                                         // Usually only for JTA: Spring synchronization might get activated here
                                         // in case of a pre-existing JTA transaction.
                                         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                                         DefaultTransactionStatus status = newTransactionStatus(
                                         definition, transaction, true, newSynchronization, debugEnabled, null);
                                         doBegin(transaction, definition);
                                         prepareSynchronization(status, definition);
                                         return status;
                                         }
                                         }

                                         // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
                                         if (debugEnabled) {
                                         logger.debug("Participating in existing transaction");
                                         }
                                         if (isValidateExistingTransaction()) {
                                         if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
                                         Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                                         if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
                                         Constants isoConstants = DefaultTransactionDefinition.constants;
                                         throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                         definition + "] specifies isolation level which is incompatible with existing transaction: " +
                                         (currentIsolationLevel != null ?
                                         isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
                                         "(unknown)"));
                                         }
                                         }
                                         if (!definition.isReadOnly()) {
                                         if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                                         throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                         definition + "] is not marked as read-only but existing transaction is");
                                         }
                                         }
                                         }
                                         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                                         return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
                                         }
```

关键的判断逻辑都在注释中标注好了，默认情况下 `@Transactional` 注解中的事务传播行为是**REQUIRED**，均不属于上面的if判断结构条件，最终到最后的 `prepareTransactionStatus` 方法，返回出去，全程没有再开启新事务，也没有挂起事务。

至此，**REQUIRED**模式得以体现。

### 3.5 【REQUIRES\_NEW】过程

将 `DemoService` 的 `test1` 方法中 `@Transactional` 注解的 `propagation` 修改为 `REQUIRES_NEW` 。重新Debug，来到 `handleExistingTransaction` 方法中：

```java
private TransactionStatus handleExistingTransaction(
    TransactionDefinition definition, Object transaction, boolean debugEnabled)
    throws TransactionException {
    // ......
    // 如果当前方法的事务行为是REQUIRED_NEW,挂起当前事务，并新建一个事务执行，执行完之后，唤醒上个事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction, creating new transaction with name [" +
                         definition.getName() + "]");
        }
        SuspendedResourcesHolder suspendedResources = suspend(transaction);
        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 | Error beginEx) {
            resumeAfterBeginException(transaction, suspendedResources, beginEx);
            throw beginEx;
        }
    }

    // ......
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
```

进入这一组分支中，这里面的步骤与之前几乎完全一致，这里咱只关注几个不太相同的部分。

#### 3.5.1 suspend执行完

通过Debug发现它返回了test2的事务信息：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671975906145-21bd42be-e971-4b0f-bc62-c29a646c844e.png)

#### 3.5.2 创建TransactionStatus后

通过Debug发现它的 `suspendedResources` 包含了test2的事务：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671975932452-e9110db8-4746-4a3e-9903-b6063c03e619.png)

#### 3.5.3 test1方法commit

```java
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
    status.setCompleted();
if (status.isNewSynchronization()) {
    TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
    doCleanupAfterCompletion(status.getTransaction());
}
if (status.getSuspendedResources() != null) {
    if (status.isDebug()) {
        logger.debug("Resuming suspended transaction after completion of inner transaction");
    }
    Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
    resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
```

在清理test1的事务缓存后，最底下有一个 `resume` 方法，它负责激活上一个事务：

#### 3.5.4 resume

```java
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
    throws TransactionException {

    if (resourcesHolder != null) {
        Object suspendedResources = resourcesHolder.suspendedResources;
        if (suspendedResources != null) {
            doResume(transaction, suspendedResources);
        }
        List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
        if (suspendedSynchronizations != null) {
            TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
            TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
            TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
            doResumeSynchronization(suspendedSynchronizations);
        }
    }
}
```

它做空校验后，会拿到当前线程中的上一个事务，并执行 `doResume` 方法，最终再绑定到事务同步管理器上。

#### 3.5.5 doResume

```less
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
    TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
}
```

发现这里重新绑定了之前被挂起的事务。

至此，**REQUIRES\_NEW**模式也得以体现。

### 3.6 【NESTED】Debug过程

将 `DemoService` 的 `test1` 方法中 `@Transactional` 注解的 `propagation` 修改为 `NESTED` 。重新Debug，来到 `handleExistingTransaction` 方法中：

```java
private TransactionStatus handleExistingTransaction(
        TransactionDefinition definition, Object transaction, boolean debugEnabled)
        throws TransactionException {
    // ......
    // 如果当前方法的事务行为是NESTED，创建一个保存点
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
        if (!isNestedTransactionAllowed()) {
            throw new NestedTransactionNotSupportedException(
                    "Transaction manager does not allow nested transactions by default - " +
                    "specify 'nestedTransactionAllowed' property with value 'true'");
        }
        if (debugEnabled) {
            logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
        }
        if (useSavepointForNestedTransaction()) {
            // Create savepoint within existing Spring-managed transaction,
            // through the SavepointManager API implemented by TransactionStatus.
            // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
            DefaultTransactionStatus status =
                    prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
            status.createAndHoldSavepoint();
            return status;
        }
        else {
            // Nested transaction through nested begin and commit/rollback calls.
            // Usually only for JTA: Spring synchronization might get activated here
            // in case of a pre-existing JTA transaction.
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, null);
            doBegin(transaction, definition);
            prepareSynchronization(status, definition);
            return status;
        }
    }

    // ......
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
```

这部分流程就跟之前不太一样了，因为涉及到保存点的概念。下面还是Debug到方法的if结构中来看：

#### 3.6.1 useSavepointForNestedTransaction

```java
protected boolean useSavepointForNestedTransaction() {
    return true;
}
```

没什么好说的，直接进if结构体吧。

#### 3.6.2 prepareTransactionStatus

```java
protected final DefaultTransactionStatus prepareTransactionStatus(
    TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
    boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

    DefaultTransactionStatus status = newTransactionStatus(
        definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
    prepareSynchronization(status, definition);
    return status;
}
```

这里面分为两个部分：创建 `TransactionStatus` ，设置同步。这两步也很简单，之前也都看过了，不再赘述。

#### 3.6.3 status.createAndHoldSavepoint

这里是设置保存点的部分。

```java
public void createAndHoldSavepoint() throws TransactionException {
    setSavepoint(getSavepointManager().createSavepoint());
}
```

很明显核心的部分是拿到 `SavepointManager` 调用 `createSavepoint` 方法。

**3.6.3.1 getSavepointManager**

```java
protected SavepointManager getSavepointManager() {
    Object transaction = this.transaction;
    if (!(transaction instanceof SavepointManager)) {
        throw new NestedTransactionNotSupportedException(
            "Transaction object [" + this.transaction + "] does not support savepoints");
    }
    return (SavepointManager) transaction;
}
```

很简单，它只是把当前的事务做了一次强转。

**3.6.3.2 createSavepoint**

```java
public Object createSavepoint() throws TransactionException {
    ConnectionHolder conHolder = getConnectionHolderForSavepoint();
    try {
        if (!conHolder.supportsSavepoints()) {
            throw new NestedTransactionNotSupportedException(
                    "Cannot create a nested transaction because savepoints are not supported by your JDBC driver");
        }
        if (conHolder.isRollbackOnly()) {
            throw new CannotCreateTransactionException(
                    "Cannot create savepoint for transaction which is already marked as rollback-only");
        }
        return conHolder.createSavepoint();
    }
    catch (SQLException ex) {
        throw new CannotCreateTransactionException("Could not create JDBC savepoint", ex);
    }
}
```

这里面它拿 `ConnectionHolder` ，最底下的return中调了 `createSavepoint` 方法来实际的创建保存点。

```kotlin
public Savepoint createSavepoint() throws SQLException {
    this.savepointCounter++;
    return getConnection().setSavepoint(SAVEPOINT_NAME_PREFIX + this.savepointCounter);
}
```

发现了原生jdbc的操作：`Connection` 对象的 `setSavepoint` 方法。

#### 3.6.4 test1方法commit

与之前没什么不同，直接commit即可。最后的清除缓存部分，因为当前事务不是全新的事务，所以没有任何动作，直接返回。

### 3.7 小结

1. 声明式事务有7种事务传播行为，默认是REQUIRED。
2. 事务传播行为的加载过程，是在事务通知织入代理对象时已经创建好了。
3. 事务传播行为的核心控制点在 `getTransaction` 和 `handleExistingTransaction` 方法中。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ldbmcs.gitbook.io/java/java-frameworks-54/spring/spring-boot/spring-boot-sheng-ming-shi-shi-wu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
