深入解析 Spring 事务管理原理及源码
Spring 事务管理(Transaction Management)是企业级应用开发中至关重要的功能之一,它确保数据操作的 原子性、一致性、隔离性、持久性(ACID)。
本篇博客将从 Spring 事务的基本概念 开始,深入 Spring 事务的实现机制 ,并对 @Transactional
注解的底层执行流程 进行源码级解析。
1. 事务的基本概念
在数据库操作中,事务是一个逻辑操作单元,必须满足 ACID 四大特性:
特性 | 说明 |
---|---|
原子性(Atomicity) | 事务内的所有操作要么全部成功,要么全部失败 |
一致性(Consistency) | 事务执行后,数据库从一个一致性状态转换到另一个一致性状态 |
隔离性(Isolation) | 并发事务相互隔离,防止数据不一致 |
持久性(Durability) | 事务提交后,数据永久保存到数据库 |
⚙️ 2. Spring 事务的核心组件
Spring 通过 声明式事务 和 编程式事务 来管理数据库事务。
2.1 Spring 事务的核心接口
组件 | 作用 |
---|---|
PlatformTransactionManager |
事务管理器接口 |
DataSourceTransactionManager |
适用于 JDBC 的事务管理器 |
JpaTransactionManager |
适用于 JPA(Hibernate)的事务管理器 |
TransactionDefinition |
事务的定义,包括隔离级别、传播行为等 |
TransactionStatus |
事务的当前状态 |
3. @Transactional
注解解析
Spring 通过 @Transactional
注解实现 声明式事务,常见用法如下:
java
@Service
public class OrderService {
@Transactional
public void createOrder() {
// 事务开始
orderDao.insertOrder();
paymentDao.processPayment(); // 若失败,事务回滚
// 事务提交
}
}
3.1 @Transactional 支持的属性
属性 | 说明 |
---|---|
propagation | 事务传播行为 |
isolation | 事务隔离级别 |
timeout | 事务超时时间 |
readOnly | 是否为只读事务 |
rollbackFor | 指定哪些异常会触发回滚 |
4. Spring 事务管理的源码解析
Spring 事务管理的核心是通过 AOP(面向切面编程) 来实现的,底层依赖于 TransactionInterceptor 和 PlatformTransactionManager 来实现事务的创建、提交、回滚等操作。
4.1 事务的创建与提交流程
1️⃣ @Transactional 代理拦截
Spring 事务使用 AOP 代理 来拦截标注了 @Transactional 注解的方法,并通过 TransactionInterceptor 来处理事务的启动、提交和回滚。具体如下:
java
public Object invoke(MethodInvocation invocation) throws Throwable {
return transactionInterceptor.invokeWithinTransaction(
invocation.getMethod(), targetClass, invocation::proceed
);
}
2️⃣ 获取事务管理器并创建事务
事务管理器(如 DataSourceTransactionManager)负责管理事务。在 doBegin() 方法中会启动一个新的事务:
java
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
Connection conn = DataSourceUtils.getConnection(dataSource);
conn.setAutoCommit(false); // 关闭自动提交,开启事务
}
3️⃣ 执行业务逻辑
当事务开始后,Spring 会执行业务方法(invocation.proceed())。如果在业务逻辑执行过程中出现异常,则会触发回滚。
4️⃣ 提交或回滚事务
当方法执行完成后,事务会根据是否抛出异常来决定提交还是回滚:
java
@Override
protected void doCommit(DefaultTransactionStatus status) {
status.getConnectionHolder().getConnection().commit();
}
@Override
protected void doRollback(DefaultTransactionStatus status) {
status.getConnectionHolder().getConnection().rollback();
}
5. 事务的传播机制
Spring 事务支持 7 种传播行为,用于控制当前事务如何传播到嵌套事务中。以下是最常用的几种传播行为及其实际应用:
传播行为实例
1️⃣ REQUIRED(默认行为
)
如果当前存在事务,则加入事务;如果当前没有事务,则新建事务。例如:
java
@Transactional(propagation = Propagation.REQUIRED)
public void method1() {
// 当前存在事务,将加入该事务
}
如果 method1() 中调用了一个没有声明事务的方法 method2(),method2() 会加入到 method1() 的事务中。
2️⃣ REQUIRES_NEW
当前方法总是会新建一个事务,暂停当前事务。例如:
java
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1() {
// 新建一个事务,当前事务会被挂起
}
当 method1() 执行时,它会暂停外部事务,并在自身内部创建一个新的事务。
3️⃣ NESTED
在当前事务中创建一个嵌套事务。嵌套事务可以独立提交或回滚,但会共享外部事务的连接。例如:
java
@Transactional(propagation = Propagation.NESTED)
public void method1() {
// 创建一个嵌套事务
}
嵌套事务在提交时不会影响外部事务,但可以独立回滚。
组合后的效果
REQUIRED + REQUIRES_NEW:会在外部事务的基础上创建新的事务,外部事务挂起,内部事务完成后恢复外部事务。
REQUIRED + NESTED:如果外部事务提交,嵌套事务也会提交;若外部事务回滚,嵌套事务也会回滚。
通过以上,应该可以很快了解Spring事务,也能更快的去排查跟定位问题。
如果你还有其他问题或想了解更多,欢迎留言交流! 😊