Spring事务的分类,原理以及注意事项

本文详细解析了SpringBoot中事务的分类与原理,重点介绍了如何利用AOP技术实现事务的声明与编程,并强调了在使用@Transactional注解时的注意事项,确保数据操作的完整性和一致性。

1.分类:

a.声明事务

b.编程事务

2.原理

AOP技术 环绕通知进行拦截

3.注意事项

不要try,因为要将异常抛出给外层

springboot中添加事务的时候如下:

加上@Transactional的用处,会使得insertUser这个方法彻底执行完毕以后才会提交事务,

期间如果异常则会回滚,数据就不会插入到数据库了。

<think>我们正在讨论Spring事务传播行为的内部实现机制。根据之前的引用,特别是引用[3]和引用[4],我们可以知道Spring事务传播行为是通过TransactionInterceptor拦截方法调用,并根据事务传播行为的定义来管理事务的创建和加入。此外,引用[5]展示了REQUIRED传播行为的示例代码。 现在,让我们深入探讨Spring事务传播行为的实现原理和机制: 1. **核心接口**:Spring事务管理的核心接口是`PlatformTransactionManager`,它定义了事务的获取、提交和回滚的基本操作(引用[4])。具体实现如`DataSourceTransactionManager`用于JDBC事务。 2. **事务拦截器**:当我们在方法上使用`@Transactional`注解时,Spring会创建一个AOP代理(通常使用JDK动态代理或CGLIB),在方法调用时,会通过`TransactionInterceptor`进行拦截(引用[3])。 3. **事务传播行为的工作流程**: - 当调用一个被`@Transactional`注解的方法时,`TransactionInterceptor`会先检查当前是否存在活动的事务(通过`TransactionSynchronizationManager`来管理线程本地变量中的事务状态)。 - 根据事务传播行为(如REQUIRED, REQUIRES_NEW等)来决定是加入当前事务还是创建新事务。 4. **具体传播行为实现**: - **REQUIRED**(默认):如果当前存在事务,则加入该事务;如果不存在,则创建一个新的事务(引用[5])。 - **REQUIRES_NEW**:无论当前是否存在事务,都创建一个新的事务。如果当前存在事务,则挂起当前事务,直到新事务完成。 - 其他传播行为如SUPPORTS、MANDATORY、NOT_SUPPORTED、NEVER、NESTED等,都有各自的处理逻辑。 5. **事务状态管理**:Spring使用`TransactionStatus`来表示一个事务的状态,包括是否是新事务、是否完成、是否回滚等。事务管理器通过`getTransaction()`方法获取事务状态,该方法会根据传播行为进行相应的处理。 6. **事务同步**:Spring通过`TransactionSynchronizationManager`来绑定事务资源(如数据库连接)到当前线程,确保在同一事务中多次获取的是同一个连接。 7. **嵌套事务**:对于嵌套事务(NESTED),Spring通过保存点(Savepoint)来实现,允许部分回滚。 8. **源码解析**:在`AbstractPlatformTransactionManager`的`getTransaction()`方法中,会根据`TransactionDefinition`(包含传播行为等属性)来决定事务的创建和加入。具体逻辑如下: - 检查当前线程是否已经存在事务(通过`TransactionSynchronizationManager`获取)。 - 根据传播行为,进行不同的处理。例如,REQUIRES_NEW会挂起当前事务(如果存在),然后创建新事务。 9. **事务的挂起与恢复**:挂起事务时,会将当前事务的资源(如数据库连接)从当前线程解绑,并存储在挂起的对象中。当新事务完成后,再恢复挂起的事务。 10. **示例**:考虑以下代码: ```java @Service public class ServiceA { @Transactional(propagation = Propagation.REQUIRED) public void methodA() { // 操作1 } } @Service public class ServiceB { @Autowired private ServiceA serviceA; @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB() { // 操作2 serviceA.methodA(); // 这里会加入methodB的事务,还是创建新事务? } } ``` 当调用`methodB`时,会创建一个新的事务(因为REQUIRES_NEW)。然后在`methodB`中调用`methodA`,由于`methodA`的传播行为是REQUIRED,而当前已有事务(即methodB创建的事务),所以`methodA`会加入该事务。 11. **注意事项**:事务传播行为是在同一个线程内有效的,跨线程时事务传播行为将失效,因为事务状态是绑定到线程的。 通过以上分析,我们了解了Spring事务传播行为的内部实现机制。总结来说,它是通过AOP拦截方法调用,利用事务管理器和事务同步管理器来协调事务的创建、加入、挂起和恢复,从而实现了各种传播行为。 现在,根据用户的要求,我们生成相关问题: §§相关问题§§ 1. Spring事务传播行为中,REQUIRES_NEW和NESTED的区别是什么? 2. 在Spring中,如何实现跨线程的事务传播? 3. 事务传播行为在分布式事务中如何工作? 4. Spring事务传播行为的实现与数据库的事务隔离级别有何关联?</think>### Spring事务传播行为的实现原理与机制 Spring事务传播行为是Spring框架事务管理的核心机制之一,它定义了**当多个事务方法相互调用时,事务应该如何传播**。其实现原理基于AOP(面向切面编程)和线程本地存储技术,主要通过以下组件协同工作: --- #### 一、核心实现组件 1. **`TransactionInterceptor`(事务拦截器)** - 在方法调用时进行拦截(基于AOP代理)[^3] - 根据`@Transactional`注解配置决定事务行为 ```java public class TransactionInterceptor extends TransactionAspectSupport { @Override public Object invoke(MethodInvocation invocation) { // 1. 获取事务属性 TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(...); // 2. 执行事务逻辑 return invokeWithinTransaction(...); } } ``` 2. **`PlatformTransactionManager`(事务管理器接口)** - 定义事务的创建、提交和回滚标准接口[^4] ```java public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition); void commit(TransactionStatus status); void rollback(TransactionStatus status); } ``` 3. **`TransactionSynchronizationManager`(事务同步管理器)** - 通过**ThreadLocal**存储当前线程的事务状态 - 管理事务资源(如数据库连接)的绑定与解绑 --- #### 二、传播行为处理流程 当调用`@Transactional`方法时: 1. **拦截方法调用** `TransactionInterceptor`拦截方法执行,解析事务属性(传播行为、隔离级别等)。 2. **检查当前事务状态** 通过`TransactionSynchronizationManager`判断当前线程是否存在活动事务。 3. **执行传播逻辑** 根据传播行为类型决定操作: ```mermaid graph TD A[方法调用] --> B{当前是否存在事务?} B -->|是| C[根据传播行为处理] B -->|否| D[创建新事务] C -->|REQUIRED| E[加入当前事务] C -->|REQUIRES_NEW| F[挂起当前事务, 创建新事务] C -->|NESTED| G[创建保存点] ``` 4. **资源绑定与执行** 将数据库连接绑定到当前线程,执行业务逻辑。 5. **提交/回滚决策** 根据执行结果和事务定义决定提交或回滚。 --- #### 三、关键传播行为实现细节 1. **REQUIRED(默认行为)** - 存在事务则加入,否则新建事务[^5] - 实现代码逻辑: ```java if (isExistingTransaction(transaction)) { // 加入现有事务 return handleExistingTransaction(def, transaction, debugEnabled); } else { // 创建新事务 return startTransaction(def, transaction, debugEnabled, suspendedResources); } ``` 2. **REQUIRES_NEW** - 总是创建新事务,挂起现有事务(如果存在) - 使用`TransactionSynchronizationManager.suspend()`挂起当前事务 - 新事务完成后恢复原事务 3. **NESTED** - 在现有事务中创建**保存点**(Savepoint) - 发生异常时回滚到保存点而非整个事务 - 仅支持部分数据库(如MySQL的InnoDB) 4. **NOT_SUPPORTED** - 挂起当前事务,在非事务环境下执行 --- #### 四、事务资源管理机制 1. **连接绑定** 通过`DataSourceUtils.getConnection()`获取连接,并绑定到当前线程的ThreadLocal。 2. **事务同步** 使用`TransactionSynchronization`接口实现事务事件回调: ```java public interface TransactionSynchronization { void beforeCommit(boolean readOnly); void afterCompletion(int status); } ``` 3. **事务状态跟踪** `DefaultTransactionStatus`对象记录: - 是否为新事务 - 是否设置了保存点 - 是否已完成 - 挂起的资源 --- #### 五、设计特点与注意事项 1. **线程绑定特性** 事务状态与线程绑定,跨线程调用会丢失事务上下文。 2. **代理机制限制** 自调用(同一类中方法互调)会绕过AOP代理,需通过`AopContext.currentProxy()`解决。 3. **传播行为与隔离级别关系** - 新建事务时继承当前事务的隔离级别 - 加入现有事务时忽略方法自身的隔离级别设置 4. **资源释放保证** 通过`finally`块确保事务资源释放: ```java try { // 执行业务逻辑 } finally { cleanupTransactionInfo(txInfo); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值