Spring事务的1道面试题
每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。
原理
Spring事务的原理是:通过AOP切面的方式实现的,也就是通过代理模式去实现事务增强。
具体过程是:对包含@Transactional
注解的方法进行拦截,然后重写,重新在方法里加入异常回滚的逻辑。而且,每个线程都是独立管理自己的事务,相互隔离。
原理简单,使用起来也简单,也就是在方法上打上@Transactional
注解,然后事务就正常生效了。也很少有人去验证异常情况下是否能真正的回滚。
Spring事务让我熟悉的地方是哪哪看起来都简单,让我陌生的地方使用时的变种较多,有时候莫名其妙的不生效。
源码
以上原理的相关源码如下:
实践出真知
但是 [半支烟] 偶尔会在编码过程中发现有些场景下的事务是失效的,总有些情况让你想不到,总有一些坑点等你去跳。
[半支烟] 觉得验证事务的最好方式就是:记住基本原则 + 动手实践。记住基本原则可以快速处理常规问题,动手实践可以验证偏门问题或者不确定的问题。
几种事务不生效的用法
如下是常见的几种Spring事务不生效的用法,有空的读者一定要牢记,对日常编码很有帮助,同时面试时也能说几句。
- private方法
Spring是通过AOP代理的方式实现事务增强的,但是private方法无法被代理,所以在private方法上打@Transactional
注解是不生效的。
- final、static修饰的方法
和private方法类似,final和static修饰的方法也无法被代理,所以@Transactional
注解也不生效。
因为,static是属于类方法,final修饰的方法无法被重写,自然也就无法植入事务增强代码。
- Bean对象没有被Spring托管
某个类一定要被Spring托管,那才能通过@Transactional
注解去增强事务。如果只有@Transactional
注解,而没有把类交给Spring托管,事务也是不生效的。类似如下情况:
// 此处没有@Service注解,此类不被spring托管,及时有@Transactional也不生效
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public final void createAndUpdateUser() {
createUser();
updateUserById();
}
public void createUser() {
User user = new User();
user.setId(2L);
user.setName("test2");
user.setEmail("test2" + "@test.com");
userMapper.insert(user);
System.out.println("create user");
}
public void updateUserById() {
User user = userMapper.findById(1L);
user.setName("admin1");
userMapper.update(user);
int i = 1 / 0; // 此处会抛出异常
System.out.println("update user");
}
}
- 异常被吞掉
如果在业务代码里,通过try......catch捕获了异常,同时又没有继续抛出异常时,Spring事务也是不生效的。
因为代理增强的逻辑就是要发现了异常,才能回滚事务。如果异常被方法本身吞掉了,则代理会认为没有异常,从而无法回滚。
- 非RuntimeException异常
Spring事务默认会回滚RuntimeException
及其子类,以及 Error
类型的异常。如果是其余异常,则不会回滚。源码处可见:
这种非RuntimeException异常场景下,需要做2个动作从而保证事务回滚。
- 捕获异常,然后抛出自定义异常。
- 自行在
@Transactional
注解中增加@Transactional(rollbackFor = XxxxxxxException.class)
属性。或者直接使用rollbackFor = Exception.class
,也就免去了第一步。
- 异步线程的场景
多个线程的场景下,只需要牢记每个线程只管理自己的事务即可。每个线程都有一个独立的事务上下文,存在ThreadLocal中,所以事务信息在不同线程之间是隔离的。
- 重灾区:在同一个类中调用本类的方法
这个失效场景,是最容易出错的,而且变种还多。在同一个类中调用本类的方法时,牢记以下2点,即可破局:
- 是否会开启事务依赖此类的第一个被外部调用的方法。如果此类的第一个被外部调用的方法有
@Transactional
注解,那事务生效。 - 调用自己内部方法时,采用的是
this.xxxMethod()
的方式,这种方式是不会走AOP代理的,所以被调用的内部方法的@Transactional
注解不生效。
如果确实需要调用内部方法,并且要事务生效的话,那只能将被调用的内部方法独立到新的类中,同时交给Spring管理。
一道面试题
以上关于事务不生效的用法都比较好记,只有在同一个类中调用本类的方法
场景下存在多种变种。具体请看这道面试题。请问以下createAndUpdateUser
方法的事务生效吗?
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public final void createAndUpdateUser() { //注意这里有final修饰
createUser();
updateUserById();
}
@Transactional
public void createUser() {
User user = new User();
user.setId(2L);
user.setName("test2");
user.setEmail("test2" + "@test.com");
userMapper.insert(user);
System.out.println("create user");
}
@Transactional(rollbackFor = Exception.class)
public void updateUserById() {
User user = userMapper.findById(1L);
user.setName("admin1");
userMapper.update(user);
int i = 1 / 0; // 此处会抛出异常
System.out.println("update user");
}
}
如果按照重灾区:在同一个类中调用本类的方法
里提到的2个原则,则事务全部生效。
如果按照final、static修饰的方法
里提到的原则,则事务全部不生效。
那结果如何呢?结果是以上方法的事务全部生效。
为什么呢?这里在补充一个原则:final修饰的方法如果带上@Transactional注解,事务情况按照被调用的方法自身的事务托管情况而定。
因为以上代码中的createUser
方法和updateUserById
方法,都有@Transactional
注解,所以都生效。
这种特殊情况也实在是让人瞠目,不过只需要牢记以上几种不生效的用法即可,谁没事儿写这种@Transactional
+ final
的代码呢?除了面试会问......
总结
本篇主要聊了几种事务不生效的用户,有兴趣的读者可以记一下。同时,还出了一道特殊场景的面试题,供读者自行实践。希望对你有帮助!
本篇完结!欢迎 关注、加V(yclxiao)交流、全网可搜(程序员半支烟)
原文链接:https://mp.weixin.qq.com/s/V5KpVk0kDhc9vWctOy7X9A
Spring事务的1道面试题的更多相关文章
- 一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 31.线程池复用的原理 32.spring是什么? 33.对Aop的理解 34.对IOC的理解 35.BeanFactor ...
- JavaSSM框架精选50道面试题
JavaSSM框架精选50道面试题 2019年02月13日 19:04:43 EerhtSedah 阅读数 7760更多 分类专栏: 面试题 版权声明:本文为博主原创文章,遵循CC 4.0 BY- ...
- java170道面试题汇总+详细解析
2013年年底的时候,我看到了网上流传的一个叫做<Java面试题大全>的东西,认真的阅读了以后发现里面的很多题目是重复且没有价值的题目,还有不少的参考答案也是错误的,于是我花了半个月时间对 ...
- 阿里面试挂了,就因为面试官说我Spring 事务管理(器)不熟练?
前言 事务管理,一个被说烂的也被看烂的话题,还是八股文中的基础股之一.但除了八股文中需要熟读并背诵的那些个传播行为之外,背后的"为什么"和核心原理更为重要. 写这篇文章之前,我 ...
- ASP.NET 经典60道面试题
转:http://bbs.chinaunix.net/thread-4065577-1-1.html ASP.NET 经典60道面试题 1. 简述 private. protected. public ...
- Java 208 道面试题:第一模块答案
目前市面上的面试题存在两大问题:第一,题目太旧好久没有更新了,还都停留在 2010 年之前的状态:第二,近几年 JDK 更新和发布都很快,Java 的用法也变了不少,加上 Java 技术栈也加入了很多 ...
- 208道面试题(JVM部分暂无答案)
这是从网上看到的一套java面试题, 答案只是一个大概, 另外题目质量参差不齐, 斟酌参考(JVM的部分暂时没有答案) 一.Java 基础 JDK 和 JRE 有什么区别? 答: JDK(Java D ...
- Spring事务管理详解_基本原理_事务管理方式
1. 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交,那在没有Spring帮我们管理事 ...
- Java 208 道面试题:Java 基础模块答案
目前市面上的面试题存在两大问题:第一,题目太旧好久没有更新了,还都停留在 2010 年之前的状态:第二,近几年 JDK 更新和发布都很快,Java 的用法也变了不少,加上 Java 技术栈也加入了很多 ...
- 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制
你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...
随机推荐
- 一张图看懂 SQL 的各种 JOIN 用法(含数据集和韦恩图)
- 云计算:基于Redis的文章投票系统(Python完整版)
| Redis的安装不懂的可前往 https://www.zeker.top/posts/9d3a5b2a/ 网上搜到的代码很多,但大多都有点小毛病(方法不可用,逻辑错误等) 自己基于网上找到的代码进 ...
- 使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书
本文介绍Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书,如需要了解Halo 2的安装,参考如何在Linux云服务器上通过Docker Compose部署安装Halo, ...
- 高校教编程是否应该将Python作为主语言
偶读一文:https://www.cnblogs.com/qing-gee/p/12941219.html 想到了这样的一个老问题,个人搞计算机软件开发.人工智能的时间已经十余年,虽然个人能力有限但是 ...
- [CEOI2007] 树的匹配 Treasury 题解
前言 题目链接:洛谷. 题目简述 给一棵树,问你这棵树的最大匹配是多少,并且计算出有多少种最大匹配. 题目分析 先来考虑较简单的最大匹配数.对于某一个结点,它有以下三种状态: 不参与匹配: 和某一个儿 ...
- 禅道项目管理系统权限绕过漏洞(QVD-2024-15263)
本文所涉及的任何技术.信息或工具,仅供学习和参考之用,请勿将文章内的相关技术用于非法目的,如有相关非法行为与文章作者无关.请遵守<中华人民共和国网络安全法>. 1. 概述 1.1 基本信息 ...
- Django集成腾讯COS对象存储
前言 最近遇到一个场景需要把大量的资源文件存储到 OSS 里,这里选的是腾讯的 COS 对象存储 (话说我接下来想搞的 SnapMix 项目也是需要大量存储的,我打算搭个 MinIO 把 24T 的服 ...
- 操作 JAR 文件
列出 JAR 文件内容 使用 jar 命令来列出 JAR 文件的内容: jar tf myapp.jar -t 选项表示列出文件,-f 表示指定 JAR 文件. 解压 JAR 文件 使用 jar 命令 ...
- 国产化适配——人大金仓V8R6(1)
本文主要记录kingbase安装及存储过程修改相关内容,或有错漏,请指正. 原数据库:Mysql8.0.31 现数据库:KingbaseES V008R006C008M001B0030 on x86_ ...
- Go plan9 汇编:内存对齐和递归
Go plan9 汇编系列文章: Go plan9 汇编: 打通应用到底层的任督二脉 Go plan9 汇编:手写汇编 Go plan9 汇编:说透函数栈 0. 前言 在 Go plan9 汇编系列文 ...