Spring 事务传播行为和隔离级别是如何实现的?

Spring 事务传播与隔离:深入实现原理

在 Spring 框架中,声明式事务管理通过 @Transactional 注解为开发者提供了极大的便利,使得开发者可以专注于业务逻辑,而将繁琐的事务控制代码交给框架处理。其核心在于对事务传播行为(Propagation)和隔离级别(Isolation)的精确控制。本文将深入剖C析 Spring 是如何实现这两大特性的。

核心实现:AOP 代理与事务管理器

Spring 事务管理的实现基石是面向切面编程(AOP)。当 Spring 容器在启动时扫描到 @Transactional 注解时,它会为该 Bean 创建一个代理对象。此后,所有对该 Bean 中带有 @Transactional 注解的方法的外部调用,都会被这个代理对象所拦截。

代理对象在拦截到方法调用后,并不会立即执行业务逻辑,而是会启动事务管理的流程。这个流程的核心参与者包括:

  • TransactionInterceptor (事务拦截器):作为 AOP 的具体实现,它在代理对象中拦截方法调用,并在方法执行前后加入事务处理的逻辑。
  • PlatformTransactionManager (平台事务管理器):这是 Spring 事务管理的核心接口,定义了获取事务、提交事务和回滚事务的基本操作。Spring 针对不同的持久化技术提供了具体的实现,如 DataSourceTransactionManager (用于 JDBC) 和 JpaTransactionManager (用于 JPA)。
  • TransactionSynchronizationManager (事务同步管理器):这是一个工具类,通过 ThreadLocal 来管理和同步事务资源(如数据库连接)和事务状态,确保在同一线程中的事务操作能够正确地进行。

事务传播行为的实现机制

事务传播行为定义了当一个事务方法被另一个事务方法调用时,事务应该如何表现。这是通过 PlatformTransactionManagergetTransaction(TransactionDefinition definition) 方法,结合 TransactionSynchronizationManager 来实现的。

以下是关键传播行为的实现流程:

  1. 方法调用与拦截: 当一个被 @Transactional 注解的方法被调用时,AOP 代理会拦截该调用,并由 TransactionInterceptor 开始处理。

  2. 获取事务状态: TransactionInterceptor 会调用 PlatformTransactionManagergetTransaction 方法来获取一个 TransactionStatus 对象。

  3. 判断当前是否存在事务: AbstractPlatformTransactionManagerPlatformTransactionManager 的一个抽象基类)中的 getTransaction 方法会首先通过 TransactionSynchronizationManager.isActualTransactionActive() 来检查当前线程是否已经存在一个激活的事务。

  4. 根据传播行为决策:

    • REQUIRED (默认值):
      • 如果当前存在事务,则直接加入该事务,共享同一个物理连接和事务。
      • 如果当前没有事务,PlatformTransactionManager 会调用底层的 doBegin 方法(例如,对于 JDBC,就是获取一个新的数据库连接,并将其自动提交设置为 false),创建一个新的事务。
    • REQUIRES_NEW:
      • 如果当前存在事务,PlatformTransactionManager 会调用 doSuspend 方法将当前事务挂起(例如,将当前的数据库连接暂时保存起来)。
      • 然后,它会像 REQUIRED 那样创建一个全新的事务,拥有独立的物理连接。当这个新事务提交或回滚后,之前被挂起的事务会通过 doResume 方法恢复。
    • NESTED:
      • 如果当前存在事务,并且底层的事务管理器支持保存点(Savepoint),例如 DataSourceTransactionManager,它会创建一个保存点。这样,内部的嵌套事务可以独立于外部事务进行回滚,而不会影响到外部事务。 如果不支持保存点,其行为通常会退化为 REQUIRED
      • 如果当前没有事务,其行为与 REQUIRED 相同。
    • SUPPORTS:
      • 如果当前存在事务,则加入该事务。
      • 如果当前没有事务,则以非事务的方式执行代码。
    • NOT_SUPPORTED:
      • 如果当前存在事务,则将其挂起,并以非事务的方式执行代码。
    • MANDATORY:
      • 如果当前存在事务,则加入该事务。
      • 如果当前没有事务,则抛出异常。
    • NEVER:
      • 如果当前存在事务,则抛出异常。
      • 如果当前没有事务,则以非事务的方式执行代码。
  5. 事务的提交与回滚:

    • 如果方法成功执行,TransactionInterceptor 会调用 PlatformTransactionManager.commit()
    • 如果方法抛出异常(默认是 RuntimeExceptionError),则调用 PlatformTransactionManager.rollback()
    • commitrollback 的具体行为也取决于传播设置。例如,对于 REQUIRED,只有最外层的事务方法返回时才会真正执行物理提交或回滚。而对于 REQUIRES_NEW,内部事务的提交和回滚是独立的。

隔离级别的实现机制

事务的隔离级别定义了一个事务中的修改对其他并发事务的可见程度。隔离级别的实现是在创建一个 事务时,由具体的 PlatformTransactionManager 实现类来完成的。

  • 设置时机: 隔离级别信息包含在 TransactionDefinition 中,当 PlatformTransactionManagerdoBegin 方法被调用以启动一个新事务时,隔离级别会被应用到底层的资源上。

  • 具体实现:

    • 对于 DataSourceTransactionManager, 在获取到一个新的 java.sql.Connection 对象后,它会调用 connection.setTransactionIsolation(isolationLevel) 方法来设置该连接的隔离级别。
    • 对于 JpaTransactionManager, 它会将隔离级别的信息传递给底层的 JPA 提供商(如 Hibernate),最终同样会作用于获取到的 JDBC 连接上。
  • 默认隔离级别 (DEFAULT): 当隔离级别设置为 DEFAULT 时,Spring 不会指定任何隔离级别,而是直接使用数据库驱动或数据源配置的默认隔离级别。

总结

Spring 事务传播行为和隔离级别的实现是一个精巧的、分层明确的设计。其核心可以概括为:

  • AOP 代理作为入口: 通过动态代理拦截 @Transactional 方法调用,为事务管理提供了切入点。
  • PlatformTransactionManager 作为策略核心: 定义了统一的事务操作接口,并针对不同持久化技术提供了具体的实现,解耦了业务代码与底层的事务细节。
  • TransactionSynchronizationManager 作为线程协调员: 利用 ThreadLocal 确保了事务状态和资源在单个线程中的正确传递和管理,是实现事务传播的关键。

通过这套机制,Spring 将复杂的事务控制逻辑封装起来,使得开发者可以通过简单的声明式注解,即可构建出稳定、可靠的事务性应用。

你可能感兴趣的:(Spring 事务传播行为和隔离级别是如何实现的?)