文章目录
- SpringBoot事务注解有哪些
- 1. `@Transactional`
- 2. `@EnableTransactionManagement`
- 3. `@TransactionalEventListener`
- Spring Boot中事务注解的原理
- 1. 注解解析与AOP代理创建
- 2. 事务拦截器的工作原理
- 举例说明Spring Boot中事务注解的传播行为
- `ServiceA.java`
- `ServiceB.java`
- 不同传播行为的效果
SpringBoot事务注解有哪些
1. @Transactional
这是Spring Boot里使用频率最高的事务注解,可用于类或者方法上。加在类上时,该类所有公共方法都会开启事务;加在方法上时,仅该方法开启事务。其常用属性如下:
propagation
:指定事务传播行为,默认是Propagation.REQUIRED
。isolation
:指定事务隔离级别,默认是Isolation.DEFAULT
。timeout
:设定事务超时时间(单位为秒),默认 -1 表示无超时限制。readOnly
:指定事务是否为只读事务,默认false
。rollbackFor
:指定哪些异常会触发事务回滚,默认仅RuntimeException
和Error
会导致回滚。noRollbackFor
:指定哪些异常不会触发事务回滚。
2. @EnableTransactionManagement
此注解用于开启Spring的声明式事务管理功能。一般需添加到Spring Boot主应用类上,这样Spring才能识别 @Transactional
注解并开展事务管理工作。
3. @TransactionalEventListener
该注解用于在事务上下文中监听事件。使用此注解的方法会在事务完成后执行,可用于处理与事务相关的后续操作,例如发送通知、记录日志等。
Spring Boot中事务注解的原理
Spring Boot的事务注解依赖于Spring框架的AOP(面向切面编程)和事务管理机制来实现,具体原理如下:
1. 注解解析与AOP代理创建
@EnableTransactionManagement
的作用:在Spring Boot应用里,在主应用类添加@EnableTransactionManagement
注解后,会触发Spring框架开启事务管理的自动配置。它会引入TransactionManagementConfigurationSelector
类,该类会根据配置情况注册事务管理相关的Bean定义,其中重要的是注册BeanFactoryTransactionAttributeSourceAdvisor
类型的切面(Advisor)。- 注解解析:Spring框架启动时会扫描所有带有
@Transactional
注解的类和方法。TransactionAttributeSource
接口负责解析@Transactional
注解中的属性,将这些属性封装成TransactionAttribute
对象,该对象包含事务的所有配置信息。 - AOP代理创建:Spring会为带有
@Transactional
注解的Bean创建AOP代理,根据目标对象是否实现接口,可能使用JDK动态代理或CGLIB代理。代理对象会拦截目标方法的调用,在方法调用前后添加事务管理逻辑。
2. 事务拦截器的工作原理
TransactionInterceptor
拦截器:BeanFactoryTransactionAttributeSourceAdvisor
切面包含TransactionInterceptor
拦截器。当代理对象的方法被调用时,TransactionInterceptor
会进行拦截。- 获取事务属性:
TransactionInterceptor
从TransactionAttributeSource
中获取目标方法的TransactionAttribute
对象,依据该对象的配置信息管理事务。 - 事务的开启、提交和回滚:
- 开启事务:根据
TransactionAttribute
中的传播行为和隔离级别,TransactionInterceptor
调用PlatformTransactionManager
开启新事务或加入已有事务。PlatformTransactionManager
是Spring提供的事务管理器接口,不同数据库和持久化框架有不同实现。 - 方法执行:事务开启后,
TransactionInterceptor
调用目标对象的实际方法执行具体业务逻辑。 - 提交事务:若目标方法正常执行完毕,未抛出异常,
TransactionInterceptor
根据TransactionAttribute
配置,调用PlatformTransactionManager
提交事务。 - 回滚事务:若目标方法抛出异常,
TransactionInterceptor
根据@Transactional
注解中的rollbackFor
和noRollbackFor
属性判断是否回滚事务,若需要则调用PlatformTransactionManager
执行回滚操作。
- 开启事务:根据
举例说明Spring Boot中事务注解的传播行为
假设存在两个服务类 ServiceA
和 ServiceB
,ServiceA
调用 ServiceB
的方法,且这些方法都添加了 @Transactional
注解。以下是相关代码及不同传播行为的示例:
ServiceA.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class ServiceA {@Autowiredprivate ServiceB serviceB;@Transactionalpublic void methodA() {// 模拟业务逻辑System.out.println("ServiceA.methodA() 开始执行");serviceB.methodB();System.out.println("ServiceA.methodA() 执行结束");}
}
ServiceB.java
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class ServiceB {// 1. Propagation.REQUIRED@Transactional(propagation = Propagation.REQUIRED)public void methodBRequired() {System.out.println("ServiceB.methodBRequired() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBRequired() 执行结束");}// 2. Propagation.REQUIRES_NEW@Transactional(propagation = Propagation.REQUIRES_NEW)public void methodBRequiresNew() {System.out.println("ServiceB.methodBRequiresNew() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBRequiresNew() 执行结束");}// 3. Propagation.NESTED@Transactional(propagation = Propagation.NESTED)public void methodBNested() {System.out.println("ServiceB.methodBNested() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBNested() 执行结束");}// 4. Propagation.SUPPORTS@Transactional(propagation = Propagation.SUPPORTS)public void methodBSupports() {System.out.println("ServiceB.methodBSupports() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBSupports() 执行结束");}// 5. Propagation.MANDATORY@Transactional(propagation = Propagation.MANDATORY)public void methodBMandatory() {System.out.println("ServiceB.methodBMandatory() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBMandatory() 执行结束");}// 6. Propagation.NOT_SUPPORTED@Transactional(propagation = Propagation.NOT_SUPPORTED)public void methodBNotSupported() {System.out.println("ServiceB.methodBNotSupported() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBNotSupported() 执行结束");}// 7. Propagation.NEVER@Transactional(propagation = Propagation.NEVER)public void methodBNever() {System.out.println("ServiceB.methodBNever() 开始执行");// 模拟可能的异常// if (true) {// throw new RuntimeException("模拟异常");// }System.out.println("ServiceB.methodBNever() 执行结束");}
}
不同传播行为的效果
Propagation.REQUIRED
:ServiceA.methodA()
调用ServiceB.methodBRequired()
时,由于methodA()
已开启事务,methodBRequired()
会加入该事务。若methodBRequired()
抛出异常,整个事务都会回滚。Propagation.REQUIRES_NEW
:ServiceA.methodA()
调用ServiceB.methodBRequiresNew()
时,methodBRequiresNew()
会创建新事务,与methodA()
的事务相互独立。若methodBRequiresNew()
抛出异常,仅回滚methodBRequiresNew()
的事务,methodA()
的事务不受影响。Propagation.NESTED
:ServiceA.methodA()
调用ServiceB.methodBNested()
时,methodBNested()
会在methodA()
的事务内部创建嵌套事务。若methodBNested()
抛出异常,仅回滚methodBNested()
的嵌套事务,methodA()
的事务可选择是否继续提交。Propagation.SUPPORTS
:ServiceA.methodA()
调用ServiceB.methodBSupports()
时,因methodA()
有事务,methodBSupports()
会加入该事务。若methodA()
未开启事务,methodBSupports()
会以非事务方式执行。Propagation.MANDATORY
:ServiceA.methodA()
调用ServiceB.methodBMandatory()
时,methodBMandatory()
会加入methodA()
的事务。若methodA()
未开启事务,调用methodBMandatory()
会抛出异常。Propagation.NOT_SUPPORTED
:ServiceA.methodA()
调用ServiceB.methodBNotSupported()
时,methodBNotSupported()
会以非事务方式执行,同时挂起methodA()
的事务。methodBNotSupported()
执行完毕后,methodA()
的事务继续执行。Propagation.NEVER
:ServiceA.methodA()
调用ServiceB.methodBNever()
时,由于methodA()
有事务,调用methodBNever()
会抛出异常。