Spring事务管理有 声明式事务 和 编程式事务 两种方式,实现对数据库操作的ACID控制。其核心思想是将事务管理与业务逻辑解耦,开发者通过简单注解或配置即可管理复杂事务。
开启Spring事务,本质上就是在Spring容器中增加了一个Advisor,拦截带有@Transaction的方法,在初始化后阶段创建代理对象。当代理对象执行方法前,设置数据库连接的autocommit改为false,在方法正常返回时执行commit,在异常时执行rollback。
本文中源码来自Spring 5.3.x分支,github源码地址:GitHub - spring-projects/spring-framework: Spring Framework
一 创建代理对象
当在配置类上使用@EnableTransactionManagement注解时,通过@Import导入了TransactionManagementConfigurationSelector类
该注解有两个属性
- proxyTargetClass:使用基于类的Cglib代理技术,默认为false。即使用JDK动态代理;
- AdviceMode:代理模式,枚举值有PROXY、ASPECTJ,默认为基于通知的JDK代理。
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
TransactionManagementConfigurationSelector是ImportSelector接口实现,在selectImports方法中,引入了两个bean:
- AutoProxyRegistrar:在初始化后阶段创建代理对象;
- 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对象:
- AnnotationTransactionAttributeSource:相当于Pointcut,判断某个类或方法上是否存在@Transactional注解;
- TransactionInterceptor:一个Advice,定义了代理逻辑;
- BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor,由AnnotationTransactionAttributeSource、TransactionInterceptor的对象组成。
二 执行事务的大体流程
2.1 相关接口
PlatformTransactionManager
:事务管理器的顶层接口,定义了事务的提交(commit
)、回滚(rollback
)和获取当前事务状态(getTransaction
)的方法。TransactionDefinition
:定义事务的属性(传播行为、隔离级别、超时时间、是否只读等)。TransactionStatus
:描述事务的运行时状态(是否完成、是否回滚等)。
PlatformTransactionManager
常见实现类有:
-
- JDBC:
DataSourceTransactionManager
(适用于原生JDBC或MyBatis) - JPA:
JpaTransactionManager
- Hibernate:
HibernateTransactionManager
- JTA:
JtaTransactionManager
(分布式事务)
- JDBC:
2.2 执行流程
当代理对象在执行某个方法时,会再次判断方法是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行
TransactionInterceptor.invoke()方法,基本流程为:
- 利用所配置的PlatformTransactionManager获取一个数据库连接(其中会处理事务传播行为);
- 修改数据库连接的autocommit为false;
- 执行MethodInvocation.proceed()方法,即执行业务方法;
- 如果方法没有抛异常,则提交事务;
- 如果方法抛了异常,则回滚事务。
// 伪代码: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
@Configuration
@EnableTransactionManagement
public class AppConfig {@Beanpublic DataSource dataSource() {// 配置数据源(如HikariCP)return new HikariDataSource();}@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}
}
- 使用@Transactional
@Service
public class OrderService {@Autowiredprivate 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
@Service
public class PaymentService {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate PaymentDao paymentDao;public void processPayment(Payment payment) {transactionTemplate.execute(status -> {try {// 执行数据库操作paymentDao.save(payment);return true;} catch (Exception e) {// 标记回滚status.setRollbackOnly();return false;}});}
}
- 直接使用PlatformTransactionManager
public void manualTransaction() {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 业务操作transactionManager.commit(status);} catch (Exception ex) {transactionManager.rollback(status);throw ex;}
}
下一篇文章中将详细介绍事务的传播机制。