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

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事务传播机制详解

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

相关文章:

  • NFS服务器实验
  • Linux Shell编程(五)
  • 快速部起一个Openwhisk平台,使用telego k8s服务部署能力内网部署
  • Linux性能监控工具nmon
  • 仿腾讯会议——视频发送接收
  • 【漫话机器学习系列】272.K近邻中K的大小(K-NN Neighborhood Size)
  • openCV1-2 图像的直方图相关
  • Ubuntu更新源服务器时出现:pk-client-error-quark
  • OBS VLC 不显示
  • 高速信号处理中的去加重、预加重与均衡技术
  • Eigen矩阵存储顺序以及转换
  • Scrapy爬取heima论坛所有页面内容并保存到MySQL数据库中
  • 智能IoT未来与边缘生态共建 | 2025 高通边缘智能创新应用大赛第六场公开课来袭!
  • SIL2/PLd 认证 Inxpect毫米波安全雷达:3D 扫描 + 微小运动检测守护工业安全
  • 中国核电信息技术峰会|麒麟信安锻造电力“数智基座“,护航核电安全新生态
  • Java求职面经分享:Spring Boot到微服务,从理论到实践
  • Even Split_CodeForces - 1666E分析与解答
  • 使用docker compose部署dify(大模型开发使用平台)
  • 通过现代数学语言重构《道德经》核心概念体系,形成一个兼具形式化与启发性的理论框架
  • 如何在 FastAPI 中合理使用 Pydantic 的 Alias
  • 提供常州网站建设/没被屏蔽的国外新闻网站
  • 网站建设报价明细表/东莞疫情最新数据
  • 如何做企业交易网站/百度快速排名技术培训
  • 做网站需要哪些方面的支出/百度seo优化服务
  • 做男女的那个视频网站/网站制作基本流程
  • 做像淘宝网的网站/企业如何进行网络推广