finally 块中使用 return 是一个常见的编程错误,它会:
跳过正常的事务提交流程。吞掉异常,使错误处理失效
导致不可预测的事务行为

Java 中 finally 和 return 的执行机制:

1. finally 块的基本特性
在 Java 中,finally 块有一个重要特性:几乎总是会执行,即使在 try 或 catch 块中有 return 语句。

public int example() {try {return 1;  // 这个 return 不会立即返回} finally {return 2;  // 这个 return 会覆盖上面的 return}
}
// 结果返回 2,而不是 1

2. finally 中 return 对异常处理的影响
当 finally 块中有 return 时,它会改变方法的正常执行流程:

@Transactional(rollbackFor = Exception.class)
public String testTransaction() {try {// 执行数据库操作 Adao.insert(recordA);// 执行数据库操作 B - 假设这里抛出异常dao.insert(recordB);  // 抛出异常return "success";} catch (Exception e) {// 捕获异常throw e;  // 重新抛出异常,期望触发事务回滚} finally {return "finally result";  // 这个 return 会干扰事务处理}
}//结果返回 finally result,而不会发生异常抛出,A操作会正常执行,B操作本身异常不会正常插入数据库

Spring 事务处理机制
1. Spring AOP 代理的工作原理
Spring 事务是通过 AOP 代理实现的,大致流程如下:

// Spring 生成的代理代码示意
public Object invoke(MethodInvocation invocation) throws Throwable {TransactionInfo txInfo = createTransactionIfNecessary();Object retVal;try {retVal = invocation.proceed();  // 调用实际方法} catch (Throwable ex) {// 处理异常并决定是否回滚事务completeTransactionAfterThrowing(txInfo, ex);throw ex;} finally {cleanupTransactionInfo(txInfo);}// 提交事务commitTransactionAfterReturning(txInfo);return retVal;
}

2. finally 中 return 对事务流程的干扰
当您的方法中上述A和B这样的代码时:

执行流程会变成:
Spring AOP 代理创建事务
调用实际的 testTransaction方法
执行 try 块中的业务逻辑
假设在 “执行数据库操作 B ”时抛出异常
catch 块捕获并重新抛出异常
执行 finally 块
finally 中的 return 语句直接返回结果,跳过了正常的异常处理流程
Spring AOP 代理无法完成事务回滚的正常流程

 Spring 事务拦截器的行为
Spring 的事务拦截器依赖于方法的正常完成或异常抛出来决定事务的提交或回滚:

// Spring 事务处理的核心逻辑
try {// 执行业务方法retVal = proceedWithInvocation();
} catch (Throwable ex) {// 如果方法抛出异常,则回滚事务if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {try {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());} catch (TransactionSystemException ex2) {// 处理回滚异常}}throw ex;  // 重新抛出原异常
}
// 如果方法正常完成,则提交事务
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

当 finally 中有 return 时,异常可能不会正常传播到这个拦截器层面,导致事务处理异常。

当然了!没有异常的情况下,事务都是可以正常插入的,异常的情况才会出现问题!

最佳实践总结:
避免在 finally 块中使用 return 语句
finally 块应该只用于资源清理工作
将 return 语句放在 try-catch 结构外部
在事务方法中特别注意控制流的处理

小Tips:

@Transactional:声明这是一个事务方法

rollbackFor = Exception.class:指定遇到 Exception 及其子类时回滚事务
默认情况下,Spring 只对 RuntimeException 和 Error 进行回滚

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93678.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93678.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/93678.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF 打印报告图片大小的自适应(含完整示例与详解)

目标:在 FlowDocument 报告里,根据 1~6 张图片的数量, 自动选择 2 行 3 列 的最佳布局;在只有 1、2、4 张时保持“占满感”,打印清晰且不变形。规则一览:1 张 → 占满 23(大图居中)…

【AI大模型前沿】百度飞桨PaddleOCR 3.0开源发布,支持多语言、手写体识别,赋能智能文档处理

系列篇章💥 No.文章1【AI大模型前沿】深度剖析瑞智病理大模型 RuiPath:如何革新癌症病理诊断技术2【AI大模型前沿】清华大学 CLAMP-3:多模态技术引领音乐检索新潮流3【AI大模型前沿】浙大携手阿里推出HealthGPT:医学视觉语言大模…

迅为RK3588开发板Android12 制作使用系统签名

在 Android 源码 build/make/target/product/security/下存放着签名文件,如下所示:将北京迅为提供的 keytool 工具拷贝到 ubuntu 中,然后将 Android11 或 Android12 源码build/make/target/product/security/下的 platform.pk8 platform.x509…

Day08 Go语言学习

1.安装Go和Goland 2.新建demo项目实践语法并使用git实践版本控制操作 2.1 Goland配置 路径**:** GOPATH workspace GOROOT golang 文件夹: bin 编译后的可执行文件 pkg 编译后的包文件 src 源文件 遇到问题1:运行 ‘go build awesomeProject…

Linux-文件创建拷贝删除剪切

文章目录Linux文件相关命令ls通配符含义touch 创建文件命令示例cp 拷贝文件rm 删除文件mv剪切文件Linux文件相关命令 ls ls是英文单词list的简写,其功能为列出目录的内容,是用户最常用的命令之一,它类似于DOS下的dir命令。 Linux文件或者目…

RabbitMQ:交换机(Exchange)

目录一、概述二、Direct Exchange (直连型交换机)三、Fanout Exchange(扇型交换机)四、Topic Exchange(主题交换机)五、Header Exchange(头交换机)六、Default Exchange(…

【实时Linux实战系列】基于实时Linux的物联网系统设计

随着物联网(IoT)技术的飞速发展,越来越多的设备被连接到互联网,形成了一个庞大而复杂的网络。这些设备从简单的传感器到复杂的工业控制系统,都在实时地产生和交换数据。实时Linux作为一种强大的操作系统,为…

第五天~提取Arxml中描述信息New_CanCluster--Expert

🔍 ARXML描述信息提取:挖掘汽车电子设计的"知识宝藏" 在AUTOSAR工程中,描述信息如同埋藏在ARXML文件中的金矿,而New_CanCluster--Expert正是打开这座宝藏的密钥。本文将带您深度探索ARXML描述信息的提取艺术,解锁汽车电子设计的核心知识资产! 💎 为什么描述…

开源 C++ QT Widget 开发(一)工程文件结构

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。 相关链接: 开源 C QT Widget 开发(一)工程文件结构-CSDN博客 开源 C…

手写C++ string类实现详解

类定义cppnamespace ym {class string {private:char* _str; // 字符串数据size_t _size; // 当前字符串长度size_t _capacity; // 当前分配的内存容量static const size_t npos -1; // 特殊值,表示最大可能位置public:// 构造函数和析构函数string(…

C++信息学奥赛一本通-第一部分-基础一-第3章-第2节

C信息学奥赛一本通-第一部分-基础一-第3章-第2节 2057 星期几 #include <iostream>using namespace std;int main() {int day; cin >> day;switch (day) {case 1:cout << "Monday";break;case 2:cout << "Tuesday";break;case 3:c…

【leetcode 3】最长连续序列 (Longest Consecutive Sequence) - 解题思路 + Golang实现

最长连续序列 (Longest Consecutive Sequence) - LeetCode 题解 题目描述 给定一个未排序的整数数组 nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。要求设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#x…

矿物分类系统开发笔记(一):数据预处理

目录 一、数据基础与预处理目标 二、具体预处理步骤及代码解析 2.1 数据加载与初步清洗 2.2 标签编码 2.3 缺失值处理 &#xff08;1&#xff09;删除含缺失值的样本 &#xff08;2&#xff09;按类别均值填充 &#xff08;3&#xff09;按类别中位数填充 &#xff08;…

《UE5_C++多人TPS完整教程》学习笔记43 ——《P44 奔跑混合空间(Running Blending Space)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P44 奔跑混合空间&#xff08;Running Blending Space&#xff09;》 的学习笔记&#xff0c;该系列教学视频为计算机工程师、程序员、游戏开发者、作家&#xff08;Engineer, Programmer, Game Developer, Author&…

TensorRT-LLM.V1.1.0rc1:Dockerfile.multi文件解读

一、TensorRT-LLM有三种安装方式&#xff0c;从简单到难 1.NGC上的预构建发布容器进行部署,见《tensorrt-llm0.20.0离线部署DeepSeek-R1-Distill-Qwen-32B》。 2.通过pip进行部署。 3.从源头构建再部署&#xff0c;《TensorRT-LLM.V1.1.0rc0:在无 GitHub 访问权限的服务器上编…

UniApp 实现pdf上传和预览

一、上传1、html<template><button click"takeFile">pdf上传</button> </template>2、JStakeFile() {// #ifdef H5// H5端使用input方式选择文件const input document.createElement(input);input.type file;input.accept .pdf;input.onc…

《用Proxy解构前端壁垒:跨框架状态共享库的从零到优之路》

一个项目中同时出现React的函数式组件、Vue的模板语法、Angular的依赖注入时,数据在不同框架体系间的流转便成了开发者不得不面对的难题—状态管理,这个本就复杂的命题,在跨框架场景下更显棘手。而Proxy,作为JavaScript语言赋予开发者的“元编程利器”,正为打破这道壁垒提…

MOESI FSM的全路径测试用例

MOESI FSM的全路径测试用例摘要&#xff1a;本文首先提供一个UVM版本的测试序列&#xff08;基于SystemVerilog和UVM框架&#xff09;&#xff0c;设计为覆盖MOESI FSM的全路径&#xff1b;其次详细解释如何使用覆盖组&#xff08;covergroup&#xff09;来量化测试的覆盖率&am…

git仓库和分支的关系

1️⃣ 仓库分支&#xff08;Repository Branch&#xff09;每个 Git 仓库都有自己的分支结构。分支决定你当前仓库看到的代码版本。示例&#xff1a;仓库分支只是局部修改&#xff0c;项目分支才是全局管理所有仓库分支的概念。wifi_camera 仓库&#xff1a; - main - dev - fe…

Linux的基本操作

Linux 系统基础操作完整指南一、文件与目录操作1. 导航与查看pwd (Print Working Directory)作用&#xff1a;显示当前所在目录的完整路径示例&#xff1a;pwd → 输出 /home/user/documents使用场景&#xff1a;当你在多层目录中迷失时快速定位当前位置ls (List)常用选项&…