Spring事务原理 一

Spring事务管理有 声明式事务 和 编程式事务 两种方式,实现对数据库操作的ACID控制。其核心思想是将事务管理与业务逻辑解耦,开发者通过简单注解或配置即可管理复杂事务。

开启Spring事务,本质上就是在Spring容器中增加了一个Advisor,拦截带有@Transaction的方法,在初始化后阶段创建代理对象。当代理对象执行方法前,设置数据库连接的autocommit改为false,在方法正常返回时执行commit,在异常时执行rollback。

本文中源码来自Spring 5.3.x分支,github源码地址:github.com/spring-proj...

一 创建代理对象

当在配置类上使用@EnableTransactionManagement注解时,通过@Import导入了TransactionManagementConfigurationSelector类。

该注解有两个属性

  1. proxyTargetClass:使用基于类的Cglib代理技术,默认为false。即使用JDK动态代理;
  2. AdviceMode:代理模式,枚举值有PROXY、ASPECTJ,默认为基于通知的JDK代理。
Java 复制代码
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;

TransactionManagementConfigurationSelector是ImportSelector接口实现,在selectImports方法中,引入了两个bean:

  1. AutoProxyRegistrar:在初始化后阶段创建代理对象;
  2. ProxyTransactionManagementConfiguration:定义Pointcut、Advice,创建Advisor。

有了这两个bean,Spring就能自行判断哪些bean需要被代理,代理逻辑是什么,从而创建代理对象。

1.1 AutoProxyRegistrar类

AutoProxyRegistrar类是ImportBeanDefinitionRegistrar接口的实现,在registerBeanDefinitions方法中,向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的beanDefinition。

而InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator,本质上是一个BeanPostProcessor。

其作用就是开启自动代理,在初始化后阶段去寻找容器中Advisor类型的Bean,判断并为某个Bean创建代理对象。

1.2 ProxyTransactionManagementConfiguration类

该类是一个配置类,它又定义了三个bean,创建了Advisor对象:

  1. AnnotationTransactionAttributeSource:相当于Pointcut,判断某个类或方法上是否存在@Transactional注解;
  2. TransactionInterceptor:一个Advice,定义了代理逻辑;
  3. BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor,由AnnotationTransactionAttributeSource、TransactionInterceptor组成。

二 执行事务的大体流程

2.1 相关接口

  • PlatformTransactionManager:事务管理器的顶层接口,定义了事务的提交(commit)、回滚(rollback)和获取当前事务状态(getTransaction)的方法。
  • TransactionDefinition:定义事务的属性(传播行为、隔离级别、超时时间、是否只读等)。
  • TransactionStatus:描述事务的运行时状态(是否完成、是否回滚等)。

PlatformTransactionManager常见实现类有:

    • JDBC:DataSourceTransactionManager(适用于原生JDBC或MyBatis)
    • JPA:JpaTransactionManager
    • Hibernate:HibernateTransactionManager
    • JTA:JtaTransactionManager(分布式事务)

2.2 执行流程

当代理对象在执行某个方法时,会再次判断方法是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行

TransactionInterceptor.invoke()方法,基本流程为:

  1. 利用所配置的PlatformTransactionManager获取一个数据库连接(其中会处理事务传播行为);
  2. 修改数据库连接的autocommit为false;
  3. 执行MethodInvocation.proceed()方法,即执行业务方法;
  4. 如果方法没有抛异常,则提交事务;
  5. 如果方法抛了异常,则回滚事务。
Java 复制代码
// 伪代码:TransactionInterceptor的核心逻辑
public Object invoke(MethodInvocation invocation) {
    // 1. 获取事务属性(@Transactional配置)
    TransactionAttribute txAttr = getTransactionAttribute(method);

    // 2. 获取事务管理器(PlatformTransactionManager)
    PlatformTransactionManager tm = determineTransactionManager(txAttr);

    // 3. 根据传播行为决定是否创建新事务
    TransactionStatus status = tm.getTransaction(txAttr);

    try {
        // 4. 执行业务方法
        Object result = invocation.proceed();

        // 5. 提交事务
        tm.commit(status);
        return result;
    } catch (Exception ex) {
        // 6. 根据异常类型回滚事务
        completeTransactionAfterThrowing(txAttr, status, ex);
        throw ex;
    }
}

三 声明式事务和编程式事务

3.1 声明式事务

即通过@Transactional让业务方法按指定的事务类型执行。

  • 创建DataSource、DataSourceTransactionManager
Java 复制代码
@Configuration
@EnableTransactionManagement
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // 配置数据源(如HikariCP)
        return new HikariDataSource();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}
  • 使用@Transactional
Java 复制代码
@Service
public class OrderService {
    @Autowired
    private OrderDao orderDao;

    // 指定传播行为和隔离级别
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public void createOrder(Order order) {
        orderDao.save(order);
        // 其他数据库操作(如更新库存)
        updateInventory(order.getItems());
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateInventory(List<Item> items) {
        // 更新库存逻辑
    }
}

3.2 编程式事务管理

  • 使用TransactionTemplate
Java 复制代码
@Service
public class PaymentService {
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Autowired
    private PaymentDao paymentDao;
    
    public void processPayment(Payment payment) {
        transactionTemplate.execute(status -> {
            try {
                // 执行数据库操作
                paymentDao.save(payment);
                return true;
            } catch (Exception e) {
                // 标记回滚
                status.setRollbackOnly();
                return false;
            }
        });
    }
}
  • 直接使用PlatformTransactionManager
Java 复制代码
public void manualTransaction() {
    TransactionDefinition def = new DefaultTransactionDefinition();
    TransactionStatus status = transactionManager.getTransaction(def);
    try {
        // 业务操作
        transactionManager.commit(status);
    } catch (Exception ex) {
        transactionManager.rollback(status);
        throw ex;
    }
}

下一篇文章中将详细介绍事务的传播机制。

相关推荐
shuair1 小时前
idea 2023.3.7常用插件
java·ide·intellij-idea
小安同学iter2 小时前
使用Maven将Web应用打包并部署到Tomcat服务器运行
java·tomcat·maven
Yvonne9782 小时前
创建三个节点
java·大数据
不会飞的小龙人3 小时前
Kafka消息服务之Java工具类
java·kafka·消息队列·mq
是小崔啊3 小时前
java网络编程02 - HTTP、HTTPS详解
java·网络·http
brevity_souls4 小时前
Spring Boot 内置工具类
java·spring boot
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven
shix .4 小时前
什么是tomcat
java·tomcat
java技术小馆4 小时前
Deepseek整合SpringAI
java·spring cloud
天荒地老笑话么5 小时前
Mac安装配置Tomcat 8
java·macos·tomcat