Java面试必问!Spring事务扩展机制(2)
TransactionAspectSupport#invokeWithinTransaction
TransactionAspectSupport#invokeWithinTransaction 是 Spring 对处理的处理。下面我们来大概分析一下它的处理过程:
上面的代码逻辑如下:
TransactionAttributeSource#getTransactionAttribute 获取事务相关的信息(TransactionAttribute),以注解型事务为例,看方法获取类上有没有标注@Transactional注解。
获取到 Spring 容器中配置的事务管理器 (PlatformTransactionManager),后面就是真正的事务处理
创建事务信息(TransactionInfo),里面包含事务管理器(PlatformTransactionManager) 以及事务相关信息(TransactionAttribute)
后面就是 Spring 对于事务的抽象操作,包含设置自动提交 false、业务操作、异常回滚事务和正常就提交事务
我们回到正题, Spring 通过创建事务信息(TransactionInfo),把数据库连接通过 TransactionSynchronizationManager#bindResource 绑定到 ThreadLocal 变量当中。然后标注到一个事务当中的其它数据库操作就可以通过TransactionSynchronizationManager#getResource 获取到这个连接。
数据库的事务是基于连接的,Spring 对于多个数据库操作的事务实现是基于 ThreadLocal。所以在事务操作当中不能使用多线程
3、Spring 事务的扩展 – TransactionSynchronization
在上面的 TransactionSynchronizationManager 类中我们知道,事务操作的时候它的当前线程还保存了 TransactionSynchronization 对象。而这个对象伴随着 Spring 对 事务处理的各个生命周期都会有相应的扩展。
TransactionSynchronization.java
public interface TransactionSynchronization extends Flushable {/** 事务提交状态 */int STATUS_COMMITTED = 0;/** 事务回滚状态 */int STATUS_ROLLED_BACK = 1;/**系统异常状态 */int STATUS_UNKNOWN = 2;void suspend();void resume();void flush();// 事务提交之前void beforeCommit(boolean readOnly);// 事务成功或者事务回滚之前void beforeCompletion();// 事务成功提交之后void afterCommit();// 操作完成之后(包含事务成功或者事务回滚)void afterCompletion(int status);}
事务的事务扩展项目中的应用场景是当订单成功之后,发送一条消息到 MQ 当中去。由于事务是和数据库连接相绑定的,如果把发送消息和数据库操作放在一个事务里面。当发送消息时间过长时会占用数据库连接,所以就要把数据库操作与发送消息到 MQ 解耦开来。可以利用 TransactionSynchronization#afterCommit 的这个方法,当数据成功保存到数据库并且事务提交了就把消息发送到 MQ 里面。
@Transactional
public void finishOrder(Order order){// 修改订单成功updateOrderSuccess(order);// 发送消息到 MQTransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){@Overridepublic void afterCommit() {mqService.send(order);}});
}
当事务成功提交之后,就会把消息发送给 MQ,并且不会占用数据库连接资源。
4、Spring 事务扩展 – @TransactionalEventListener
在 Spring framework 4.2 之后还可以使用@TransactionalEventListener处理数据库事务提交成功后再执行操作。这种方式比 TransactionSynchronization 更加优雅。它的使用方式如下:
@Transactionalpublic void finishOrder(Order order){// 修改订单成功updateOrderSuccess(order);// 发布 Spring Event 事件applicationEventPublisher.publishEvent(new MyAfterTransactionEvent(order));}@Slf4j@Componentprivate static class MyTransactionListener {@Autowiredprivate MqService mqService;@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)private void onHelloEvent(MyAfterTransactionEvent event) {Order order = event.getOrder();mqService.send(order);}}// 定一个事件,继承自ApplicationEvent private static class MyAfterTransactionEvent extends ApplicationEvent {private Order order;public MyAfterTransactionEvent(Object source, Order order) {super(source);this.order = order;}public Order getOrder() {return order;}}
它的实现原理是当 Spring Bean 的方法标注了通过 TransactionalEventListenerFactory#createApplicationListener创建 ApplicationListenerMethodTransactionalAdapter 然后在事件回调当中创建 TransactionSynchronization的实现类TransactionSynchronizationEventAdapter。并且通过 TransactionSynchronizationManager.registerSynchronization 把 TransactionSynchronizationEventAdapter 注册到当前线程当中。
TransactionSynchronizationEventAdapter
private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter {private final ApplicationListenerMethodAdapter listener;private final ApplicationEvent event;private final TransactionPhase phase;public TransactionSynchronizationEventAdapter(ApplicationListenerMethodAdapter listener,ApplicationEvent event, TransactionPhase phase) {this.listener = listener;this.event = event;this.phase = phase;}@Overridepublic int getOrder() {return this.listener.getOrder();}@Overridepublic void beforeCommit(boolean readOnly) {if (this.phase == TransactionPhase.BEFORE_COMMIT) {processEvent();# 最后现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。**[资料获取方式:戳这里免费下载](https://gitee.com/vip204888/java-p7)**较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。**[资料获取方式:戳这里免费下载](https://gitee.com/vip204888/java-p7)**![](https://img-blog.csdnimg.cn/img_convert/d8c9b612ad20b889af080d1480d0bc3f.png)
Java面试必问!Spring事务扩展机制(2)相关推荐
- Java 面试必问题目,Java 后端校招面试题
字节跳动一面: 自我介绍,主要讲讲做了什么和擅长什么 看你项目做 Spring 比较多, 问一下 Spring 相关的东西, IoC 是什么概念? Bean 的默认作用范围是什么?其他的作用范围? 索 ...
- 面试必问:JVM类加载机制详细解析
前言 在Java面试中,简历上有写JVM(Java虚拟机)相关的东西,JVM的类加载机制基本是面试必问的知识点. 类的加载和卸载 JVM是虚拟机的一种,它的指令集语言是字节码,字节码构成的文件是cla ...
- Java面试必问!javasocket服务端持久化
前言 最近刷到了一句耐人寻味的话,"解决雪崩问题的最好办法是不发生雪崩". 不论是在硅谷互联网公司里还是在国内的互联网平台上,曾多次遇到过海量规模的交易瞬间吞噬平台的悲惨故事. 核 ...
- 面试必问的 JVM 类加载机制,你懂了吗?
前言 本次带来 JVM 的另一块重要内容,类加载机制,不废话,直接开怼. 正文 1.类加载的过程. 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化 ...
- 今年Java面试必问的这些技术面,看完这一篇你就懂了
说明 Java生鲜电商平台中由于采用了微服务架构进行业务的处理,买家,卖家,配送,销售,供应商等进行服务化,但是不可避免存在分布式事务的问题. 业界有很多的解决方案,对此我相信大家都百度一下子就有很多 ...
- Java面试必问的HashMap,java软件工程师面试话术
前言 我们从一个问题引入今天的主题. 在日常业务开发中,我们可能经常听到 DBA 对我们说"不要"(注意:不是禁止)使用 join,那么为什么 DBA 对 join 这么抵触呢?是 ...
- 继续卷!面试又问Spring 事务有几种传播行为和隔离级别?
怕什么真理无穷 进一步有近一步的欢喜 面试又被问到了事务,来吧,要么卷起来,要么躺平.卷不动躺平会不会导致数据不一致? 事务概念 事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序 ...
- 阿里Java面试必问:java多线程实例
基于 Servlet 容器的 Web MVC 身为 Java 开发者,对于 Spring 框架并不陌生.它起源于 2002 年.Rod Johnson 著作<Expert One-on-One ...
- 网易Java面试必问:月薪20k+的Java面试都问些什么
前言 不知道你们发现没有,在很多互联网公司基本上都是80后,90后居多,很少还有超过40岁的程序员.可能很多人心里都有一个疑问,那就是这些40多岁的程序员都干嘛去了呢?创业显然只是极少数的人,至于管理 ...
最新文章
- 第11届 蓝桥杯-第1、2次模拟(软件类)真题-(2020年3月、4月)-官方讲解视频
- Neo4j:在Neo4j浏览器的帮助下探索新数据集
- [PALAPALA] 无题 - 外来的和尚会念经
- 努力只是因为想去做想做的事
- java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRunt
- spring-boot 整合redis作为数据缓存
- ASP.NET程序中 抛出Thread was being aborted. 异常(转)
- PWM波转DC直流之二阶RC低通滤波器设计
- 洛谷 P1653 猴子 解题报告
- xss.haozi.me
- Photoshop-选区的应用
- 基于 OpenVINO™ 的 AI 视觉应用基础课学习笔记(三)深度学习简介
- FANUC机器人的主板结构和电缆连接示意图介绍
- php关注账号,一键关注微信公众平台账号
- Qt编写安防视频监控系统5-视频回放
- android 4.4 电池电量管理底层分析(C\C++层)
- xss labs 挑战之旅
- 【软件2.0】软件2.0时代来了!特斯拉AI负责人说:神经网络正在改变编程
- 提高晚上学习效率的11个方法
- vs数据库访问出现Object reference not set to an instance of an object. 错误解决办法
热门文章
- 水刀行业调研报告 - 市场现状分析与发展前景预测
- 浙大计算机学院绩点,浙江大学学分制管理暂行规定-浙江大学本科生院.doc
- 经常玩电脑正确的坐姿_「姿态训练」保持良好坐姿的八个步骤
- oracle窗口累计函数,oracle 窗口函数 (keep)
- 终于升级?89年的Linux内核C语言“跟上时代”转成现代C
- 从摩托罗拉、诺基亚再到航空领域应用,这款开源数据库的成功如何成就天才程序员?...
- 官宣!DolphinScheduler 毕业成为 Apache 软件基金会顶级项目
- 京东金融品牌升级,为用户做精准决策,打造金融机构的“第二增长场景”
- 完了!Oracle 被虐!MySQL 登顶 Top1!原来这么多人都在用
- 如何用 Python 画一个纸飞机?| 原力计划