【Spring源码分析】透过源码看透Spring事务

阅读此需阅读下面这些博客先
【Spring源码分析】Bean的元数据和一些Spring的工具
【Spring源码分析】BeanFactory系列接口解读
【Spring源码分析】执行流程之非懒加载单例Bean的实例化逻辑
【Spring源码分析】从源码角度去熟悉依赖注入(一)
【Spring源码分析】从源码角度去熟悉依赖注入(二)
【Spring源码分析】@Resource注入的源码解析
【Spring源码分析】循环依赖的底层源码剖析
【Spring源码分析】Spring的启动流程源码解析
【Spring源码分析】解析配置类-ConfigurationClassPostProcessor源码分析
【Spring源码分析】Spring之AOP底层源码解析和@Async源码解析

看这篇之前一定要看我的上一篇源码分析AOP的,这篇不会讲述AOP的内容,主要是分析对应的Advice。

透过源码看透Spring事务

  • 一、EnableTransactionManagement 注解如何开启声明事务的?
  • 二、TransactionInterceptor 源码分析
    • 开启事务源码分析
      • 开启事务 startTransaction 方法源码分析
    • 提交事务 commitTransactionAfterReturning 方法源码分析
    • 回滚 completeTransactionAfterThrowing 源码解析
  • 三、总结

有些人应该是不愿意看源码的,这里先直接放我总结的图吧,也是大家想知道的Spring的事务传播机制:

请添加图片描述

一、EnableTransactionManagement 注解如何开启声明事务的?

在配置类上配置 EnableTransactionManagement 这个注解会往容器中注入俩个Bean,一个是判断Spring创建Bean时找到容器的Advisor进行AOP,一个是对应的Advisor。

在这里插入图片描述在这里插入图片描述可以看见上面导入了 AutoProxyRegister 和 ProxyTransactionManagementConfiguration 这俩配置类。
AutoProxyRegister 配置类会向容器内注入 InfrastructureAdvisorAutoProxyCreator 这个BeanPostProcessor,它在Bean的初始化后阶段就会判断是否进行AOP,然后通过ProxyFactory去得到对应代理对象放入单例池中,这前面都有叙述,这篇不阐述。

在这里插入图片描述ProxyTransactionManagementConfiguration 会向容器内注入一个 Advisor,这个 Advisor 的 Pointcut 就是判断方法或者类上是否有 @Transaction 注解,有的话就符合要求:

在这里插入图片描述

二、TransactionInterceptor 源码分析

TransactionInterceptor 就是对应的 Advice,我们分析过 ProxyFactory 源码,当拿到代理对象去执行某方法的时候,就是先执行符合条件的 Advice 链,而 TransactionInterceptor 就是事务代理逻辑的一环,也是声明式事务背后的主要处理逻辑。

  1. 首先是获取到 @Transaction 注解的属性值然后封装成了一个 TransactionAttribute 对象;
    在这里插入图片描述

  2. 然后获取到容器内的 TransactionManager 数据库管理对象,应该为 PlatformTransactionManager 类型,从容器内获取到后强转为 PlatformTransactionManager 类型。
    在这里插入图片描述在这里插入图片描述

  3. 然后的话在 createTransactionIfNecessary 方法中进行开启事务,这里涉及到开启事务的整个过程,Spring提供的事务传播机制也是在这里进行实现那的,非常关键的方法;
    在这里插入图片描述

  4. 若没有其他AOP行为了的话,这一步就该执行目标方法了,就是去执行一堆SQL~

在这里插入图片描述

  1. 若执行目标方法这个过程抛出了异常,就尝试进行回滚,由于事务的传播机制的存在,回滚也有具体的逻辑的,不是直接回滚。
    在这里插入图片描述

  2. 如果没有异常发送的话,就提交事务,也是由于传播机制的存在,提交也不是瞎鸡儿提交的,有具体的逻辑。

在这里插入图片描述

下面的话就对开启事务、回滚、提交这三个逻辑进行具体分析。

开启事务源码分析

就是通过注入容器的 PlatformTransactionManager 去开启对应事务(开发中如果需要手动去开启事务,也是通过注入 PlalformTransactionManager#getTransaction 去是实现的)ka开始事务本身是一个简单的操作,但是由于扩展了事务传播机制,这个 getTransaction 也随之变的复杂起来了,分开解析。

  1. 若是首次开启事务,就是不存在事务内调用了另一个@Transaction 方法。这个时候若事务的传播机制是 Mandatory,那就直接抛出异常,这种事务传播机制不允许你首次开启事务;
    在这里插入图片描述

  2. 依旧是首次开启事务,若事务传播机制是 Require、Require_New、Nested ,就会调用 startTransaction 去开启一个事务(开启事务这个方法最后解析)
    在这里插入图片描述

  3. 若是已经在开启事务的基础上尝试开启事务,首先是会从ThreadLocal上下文中获取到对应数据库连接对象(这个在开启事务中会阐述,这里先知道一下),然后封装到 DataSourceTransactionObject 对象中,并设置 newConnectionHolder 这个标记为为false,表示不是自己创建的。

在这里插入图片描述

  1. 随后会根据上面那个返回的数据源对象去判断当前线程是否存在一个事务,如果存在就去执行 handleExistingTransaction 方法,去执行存在事务对应的逻辑
    在这里插入图片描述判断当前线程是否存在一个事务的逻辑,其实就是判断上面从上下文是否可以获取到对应的数据库连接对象

在这里插入图片描述

  1. 接下来执行对应存在事务对应的逻辑了

如果事务的传播机制是 Never 的话直接抛出异常:

在这里插入图片描述
如果事务传播机制是 Not_Supported 将事务进行挂起,然后正常去执行就好了(就是不受事务的传播机制所影响了)

在这里插入图片描述
如果事务传播机制是 Require_New ,挂起原本事务,然后新开启一个事务:

在这里插入图片描述
如果事务传播机制是 Nested ,则创建一个 savepoint ,正常使用此事务(如果使用的是 JTA 事务管理器就会新开启一个事务,和 Require_New 一样了都)

在这里插入图片描述若是其他事务传播机制,就正常去执行,仍然是在上一个事务基础上,这里说的是 Require、Support、Mandatory,Mandatory 是在第一次抛异常的,而这里是嵌入的 @Transaction,则仍然会继续执行。

在这里插入图片描述大致流程其实说完了,现在咱细看一下开启事务和挂起事务的源码

开启事务 startTransaction 方法源码分析

在这里插入图片描述doBegin 方法源码分析:

  1. 若当前事务没有创建数据库连接,则创建一个数据库连接对象
    在这里插入图片描述
  2. 设置一些参数,如:事务隔离级别、autoCommit、readOnly等等

在这里插入图片描述

  1. 将数据库连接绑定到上下文中,供后续调用

在这里插入图片描述在这里插入图片描述在这里插入图片描述

prepareSynchronization 方法解析:

该方法就是搞了个上下文标记当前线程是开启了事务的

在这里插入图片描述在这里插入图片描述在这里插入图片描述

提交事务 commitTransactionAfterReturning 方法源码分析

  1. 若配置了强制回滚就会直接回滚,不会提交

在这里插入图片描述

  1. 如果配置了 savepoint,就会把savepoint设置为空,表示已经后续回滚也和这个savepoint没关系了,就咱说嵌入Transaction然后事务的传播机制是 Nested 的时候;如果这是一个新的事务,那就会进行提交,新事务就是说第一次创建的,没另一个Transaction嵌入;

在这里插入图片描述

  1. 恢复挂起的资源到当前线程中,就是将之前挂起的status重新放入到resources上下文中
    在这里插入图片描述

回滚 completeTransactionAfterThrowing 源码解析

首先是判断抛出的异常是否符合我们配置的 rollbackFor,norollbackFor 规则,如果是不符合回滚规则的直接提交,否则走回滚逻辑:
在这里插入图片描述

  1. 如果设置了 savepoint 就回滚到 savepoint 的位置,这就是 Nested ,嵌入Transaction 时可能发生的情况

在这里插入图片描述

  1. 如果是新事务的话就直接回滚

在这里插入图片描述

三、总结

简单阐述这个切面 实现就是:开启事务->执行目标对象方法->提交/回滚

考虑到Spring搞了个事务传播机制,那就需要考虑传播机制带来的影响咯,默认是 Require 传播机制,理解为正常事务就好了。

直接看图吧:

请添加图片描述

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

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

相关文章

书生浦语笔记一

2023年6月,InternLM的第一代大模型正式发布。仅一个月后,该模型以及其全套工具链被开源。随后,在8月份,多模态语料库chat7B和lagent也被开源。而在接下来的9月份,InternLM20B的开源发布进一步加强了全线工具链的更新。…

所有企业都在用的微服务框架,需要多强的服务集成能力?

在数字化时代,随着业务规模的扩大和系统复杂性的增加,传统的单体应用架构由于其固有的局限性,已无法高效支撑企业日益增长的业务需求。 为了突破这一瓶颈,微服务架构以其独特的优势崭露头角,逐渐成为企业数字化转型的…

腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践

腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践 文章目录 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践引言《2023腾讯云容器和函数计算技术实践精选集》整体评价特色亮点分析Serverless与Kubernetes的…

【刷题】 二分查找入门

送给大家一句话: 总有一天,你会站在最亮的地方,活成自己曾经渴望的模样—— 苑子文 & 苑子豪《我们都一样 年轻又彷徨》 二分查找入门 1 前言2 Leetcode 704. 二分查找2.1 题目描述2.2 算法思路 3 Leetcode 34. 在排序数组中查找元素的第一个和最后…

学习笔记——C语言基本概念指针(下)——(8)

1.指针和数组 数组指针 -- 指向数组的指针。 指针数组 -- 数组的元素都是指针。 换句话理解就是:数组指针就是个指针,指针数组就是个数组。 1.1数组指针 数组指针:指向数组的指针; 先回顾一下数组的特点: 1.相…

【C语言】联合体、枚举: 联合体与结构体区别,枚举的优点

目录 1、联合体 1.1、什么是联合体 1.2、联合体的声明 1.3、联合体的特点 1.4、联合体与结构体区别 1.5、联合体的大小 2、枚举 2.1、枚举类型的声明 2.2、枚举类型的优点 3、三种自定义类型:结构体、联合体、枚举 正文 1、联合体 1.1、什么是联合体 联…

如何使用route-detect在Web应用程序路由中扫描身份认证和授权漏洞

关于route-detect route-detect是一款功能强大的Web应用程序路由安全扫描工具,该工具可以帮助广大研究人员在Web应用程序路由中轻松识别和检测身份认证漏洞和授权漏洞。 Web应用程序HTTP路由中的身份认证(authn)和授权(authz&…

题目:小明的背包5(蓝桥OJ 1178)

问题描述&#xff1a; 解题思路&#xff1a; 分组背包模板题&#xff0c;与优化01背包的不同之处在于第一维不可省略&#xff0c;要写s循环。注意要初始化 #include <bits/stdc.h> using namespace std; const int N 1e3 9; int dp[N][N]; // 分组背包模板&#xff0c;…

代码随想录阅读笔记-二叉树【平衡二叉树】

题目 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a;一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 返回 true 。 示例 2: 给定二叉树 [1,2,…

ZKFair 创新之旅,新阶段如何塑造财富前景

在当前区块链技术的发展中&#xff0c;Layer 2&#xff08;L2&#xff09;解决方案已成为提高区块链扩容性、降低交易成本和提升交易速度的关键技术&#xff0c;但它仍面临一些关键问题和挑战&#xff0c;例如用户体验的改进、跨链互操作性、安全性以及去中心化程度。在这些背景…

Unity中UI系统1——GUI

介绍 工作原理和主要作用 基本控件 a.文本和按钮控件 练习&#xff1a; b.多选框和单选框 练习&#xff1a; 用的是第三种方法 c.输入框和拖动框 练习&#xff1a; 练习二&#xff1a; e.图片绘制和框 练习&#xff1a; 复合控件 a.工具栏和选择网格 练习&#xff1a; b.滚动视…

纷享销客如何向生态型CRM进化 创始人罗旭给出了答案

自己挣1块钱时&#xff0c;渠道合作伙伴能够挣1块甚至更多。这是纷享销客与生态共建之道。 2024年纷享销客北方战区渠道生态伙伴发展共建会于日前在北京举行。在这场主题为“聚力纷享共赢巅峰”的大会上&#xff0c;各方探讨了企业高质量增长之源与SaaS行业渠道发展之路&#…

云渲染实用工具:3ds max怎么改低版本?

3ds Max是建模领域广泛采用的专业软件&#xff0c;它通过定期更新来不断增强功能和提升性能。但这些频繁的更新有时会导致一些插件暂时无法与新版本完全兼容。为了解决这个问题&#xff0c;设计师们可以采用一个简单有效的方法&#xff0c;那就是将较新版本的3ds Max文件进行版…

基于Unity+Vue3通信交互的WebGL项目发布实践

基于UnityVue3通信交互的WebGL项目发布实践 实践路线 基于UnityVue3通信交互的WebGL项目发布实践问题背景准备工作解决方案项目实践小目标搭建Unity测试项目 创建Vue3测试项目运行项目验证unity和vue通信功能总结与展望 问题背景 我们最近需要把unity开发的pc项目迁移到web端&…

吴恩达深度学习笔记:浅层神经网络(Shallow neural networks)3.9-3.11

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第三周&#xff1a;浅层神经网络(Shallow neural networks)3.9 神 经 网 络 的 梯 度 下 降 &#xff08; Gradient descent for neural networks&#xff09;3.10&#xff08;选修&#xff0…

C#让标题栏闪烁着动起来的方法

目录 1.API函数FlashWindow &#xff08;1&#xff09;添加命名空间 &#xff08;2&#xff09;声明DllImport方法 &#xff08;3&#xff09;FlashWindow函数 2.P/Invoke 3.再来一个示例 在Windows系统中&#xff0c;当程序在后台运行时&#xff0c;如果某个窗体的提示信…

环境配置——已解决ModuleNotFoundError: No module named ‘cv2’(python)

一、报错代码 在网上搜到不少用Python处理图形的代码&#xff0c;于是复制别人的代码直接运行却报错&#xff0c;得到的结果却是&#xff1a;已解决ModuleNotFoundError: No module named ‘cv2’。&#xff08;当时心里瞬间凉了一大截&#xff0c;最后顺利解决了&#xff0c;顺…

软考 系统架构设计师系列知识点之云原生架构设计理论与实践(8)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之云原生架构设计理论与实践&#xff08;7&#xff09; 所属章节&#xff1a; 第14章. 云原生架构设计理论与实践 第2节 云原生架构内涵 14.2 云原生架构内涵 关于云原生的定义有众多版本&#xff0c;对于云原生架构的…

脑部肿瘤检测YOLOV8

脑部肿瘤检测&#xff0c;采用YOLOV8训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV调用&#xff0c;支持C/PYTHON/ANDORID开发脑部肿瘤检测YOLOV8

如何在Plesk面板备份网站

本周有一个客户&#xff0c;购买Hostease的Windows虚拟主机&#xff0c;咨询我们的在线客服&#xff0c;询问Windows虚拟主机Plesk面板是否提供备份功能。我们为用户提供教程&#xff0c;用户很快完成了数据备份。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您…