当前位置: 首页 > ops >正文

Java异常分类与Spring事务回滚机制深度剖析


Java异常分类与Spring事务回滚机制深度剖析

作者:AI助手
日期:2025-05-22

一、前言

在企业级开发中,Spring的声明式事务(@Transactional)极大简化了数据一致性的管理。但很多开发者对事务回滚与异常的关系事务传播机制及其背后源码实现理解不够深入,容易踩坑。本文将系统梳理相关理论与实践,深入源码,助你彻底掌握Spring事务。


二、Java异常分类

2.1 异常体系结构

Java异常体系如下图:

Throwable
├── Error(严重错误,JVM级,程序无法处理)
└── Exception├── Checked Exception(受检异常,如IOException、SQLException)└── RuntimeException(运行时异常,如NullPointerException、IllegalArgumentException)

2.2 受检与非受检异常

  • Checked Exception(受检异常)
    必须显式声明throws或捕获处理。比如IOExceptionSQLException
  • Unchecked Exception(运行时异常)
    编译器不强制处理。比如NullPointerExceptionIllegalArgumentException

口诀:
受检异常要声明,运行时异常可不管。


三、Spring事务原理

3.1 声明式事务的实现方式

Spring主要通过AOP代理实现声明式事务:

  1. 容器在Bean初始化时,自动为带有@Transactional的方法生成代理对象(JDK动态代理或CGLIB)。
  2. 代理对象拦截方法调用,事务拦截器(TransactionInterceptor)负责事务管理。
流程简图
业务方法调用↓
代理对象(AOP)↓
TransactionInterceptor(事务拦截器)↓
PlatformTransactionManager(策略接口,不同实现)↓
数据库事务

3.2 事务拦截器核心源码

// TransactionInterceptor#invoke
public Object invoke(final MethodInvocation invocation) throws Throwable {TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);PlatformTransactionManager tm = determineTransactionManager(txAttr);TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal;try {retVal = invocation.proceedWithInvocation(); // 执行业务代码} catch (Throwable ex) {completeTransactionAfterThrowing(txInfo, ex); // 异常处理throw ex;} finally {cleanupTransactionInfo(txInfo); // 清理}commitTransactionAfterReturning(txInfo); // 正常提交return retVal;
}

四、Spring事务回滚机制与异常关系

4.1 默认回滚规则

  • 只对RuntimeExceptionError自动回滚
  • Checked Exception(受检异常)不会自动回滚,除非配置rollbackFor
源码分析
// DefaultTransactionAttribute#rollbackOn
public boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error);
}

4.2 自定义回滚规则

可通过@Transactional注解参数配置:

  • rollbackFor:指定哪些异常需要回滚
  • noRollbackFor:指定哪些异常不回滚

示例:

@Transactional(rollbackFor = IOException.class, noRollbackFor = NullPointerException.class)
public void foo() throws IOException { ... }
源码分析
// RuleBasedTransactionAttribute#rollbackOn
public boolean rollbackOn(Throwable ex) {// 遍历rollbackRules,匹配异常类型// ...省略if (winner == null) {return super.rollbackOn(ex);}return !(winner instanceof NoRollbackRuleAttribute);
}

4.3 捕获异常对事务的影响

如果业务代码catch住异常且未继续抛出,Spring事务感知不到异常,不会回滚

示例:

@Transactional
public void bar() {try {// 业务代码} catch (Exception e) {// 异常被吞,事务不会回滚}
}

手动回滚方法:

@Transactional
public void baz() {try {// 业务代码} catch (Exception e) {TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}
}

五、Spring事务传播机制(Propagation)

5.1 传播行为类型

Spring定义了7种事务传播行为,主要包括:

  • REQUIRED(默认):如果当前存在事务,则加入,否则新建事务
  • REQUIRES_NEW:总是新建事务,挂起原有事务
  • NESTED:嵌套事务,依赖底层数据库支持
  • SUPPORTSMANDATORYNOT_SUPPORTEDNEVER

5.2 传播机制源码分析

// AbstractPlatformTransactionManager#getTransaction
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {Object transaction = doGetTransaction();if (isExistingTransaction(transaction)) {// 已有事务,处理不同传播行为return handleExistingTransaction(definition, transaction, debugEnabled);}// 无事务,处理不同传播行为// ...
}

六、设计模式在Spring事务中的应用

  • 代理模式:AOP代理实现方法拦截
  • 策略模式PlatformTransactionManager接口多策略实现(JDBC、JPA等)
  • 模板方法模式AbstractPlatformTransactionManager定义事务模板,子类实现细节
  • 责任链模式:AOP拦截器链
  • 适配器模式:不同数据源通过实现同一接口适配Spring事务

七、常见误区与最佳实践

7.1 常见误区

  1. 误认为所有异常都会回滚
    只有运行时异常和Error才自动回滚。

  2. 捕获异常未手动回滚
    异常被catch并吞掉,需手动调用setRollbackOnly()

  3. 内部方法调用失效
    同类内部调用@Transactional方法不会被AOP代理增强,事务无效。

7.2 最佳实践

  • 业务异常建议继承RuntimeException
  • 不要随意捕获异常,交给Spring处理回滚
  • 需要受检异常回滚时,明确指定rollbackFor
  • 避免同类内部调用@Transactional方法

八、案例演示

@Service
public class DemoService {// 运行时异常,事务会回滚@Transactionalpublic void runtimeEx() {throw new RuntimeException("运行时异常,事务回滚");}// 受检异常,事务不会回滚@Transactionalpublic void checkedEx() throws IOException {throw new IOException("受检异常,事务不会回滚");}// 指定受检异常回滚@Transactional(rollbackFor = IOException.class)public void checkedExRollback() throws IOException {throw new IOException("受检异常,事务回滚");}// 捕获异常,不回滚@Transactionalpublic void catchEx() {try {throw new RuntimeException("异常被捕获,事务不会回滚");} catch (Exception e) {// 异常被吞}}// 手动强制回滚@Transactionalpublic void manualRollback() {try {throw new RuntimeException("异常被捕获,事务不会回滚");} catch (Exception e) {TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}
}

九、总结与速记口诀

  1. 异常类型记: 运行时异常默认回滚,受检异常需声明。
  2. 回滚原理记: 事务拦截异常,运行时异常和错误才回滚。
  3. 自定义规则记: 指定回滚例外,规则优先匹配。
  4. 异常捕获记: 异常被吞事务不回滚,强制回滚需手动指定。
  5. 内部调用记: 内部调用无事务,代理之外才生效。
  6. 传播行为记: 传播行为定范围,异常影响全局。

十、参考资料与源码链接

  • Spring官方事务文档
  • TransactionInterceptor 源码
  • AbstractPlatformTransactionManager 源码
  • Spring事务传播机制详解

欢迎收藏、点赞、转发!如有问题欢迎评论区探讨。

http://www.xdnf.cn/news/8085.html

相关文章:

  • 电子电路:为什么会产生电流超前或者滞后于电压的情况?
  • 实战演练:天猫商品详情页动态数据 API 接口开发与调用
  • Nginx 部署前端项目dist文件到局域网然后ngrok部署到公网
  • 如何使用AI为WordPress生成图片
  • 通过Python 在Excel工作表中轻松插入行、列
  • 编译xiaozhi-esp32-server-java遇到的报错
  • 痉挛性斜颈护理指南:多维度守护颈部健康
  • 快速创建 Vue 3 项目
  • ss、lsof 命令
  • AI与.NET技术实操系列(六):实现图像分类模型的部署与调用
  • 密码学标准(Cryptography Standards)介绍
  • 用vue canvas画一个能源电表和设备的监测图
  • Python的切片操作[::-1]
  • 集团企业数字化转型及集团数字化整体蓝图未来五年实施方案
  • 【图像处理入门】1. 数字图像的本质:从像素到色彩模型
  • 【计算机网络】网络层——IP协议
  • Java大厂面试:JVM调优、高并发订单处理与大数据服务场景解析
  • leetcode hot100刷题日记——9.矩阵置零
  • PYTORCH_CUDA_ALLOC_CONF基本原理和具体示例
  • 解决leetcode第3548题.等和矩阵分割II
  • asp.net core 添加 EntityFrame
  • 并发编程之并发容器类
  • [Java恶补day3] 128. 最长连续序列
  • 【愚公系列】《Manus极简入门》054-家庭冲突调解师:“家庭和谐使者”
  • 使用 Docker 搭建 PyWPS 2.0 服务全流程详解
  • Oracle 的V$ACTIVE_SESSION_HISTORY 视图
  • XC3588H搭载国产麒麟系统可用于政务/社保一体机吗?
  • 小球弹弹弹
  • 企业级AI搜索解决方案:阿里云AI搜索开放平台
  • 《数据资产价值与收益分配评价模型》