Spring源码系列-Spring事务

news2025/3/15 14:52:07

声明式事务

spring事务,是通过数据库连接来实现的,当前线程中保存了一个map,key是数据原,value是数据库连接

我们说的同一个事务,其实指的是同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。

如果在不同的线程,拿到的数据库连接肯定是不一样的,那么肯定也就是不同的事务,所以不要在事务中开启另外的线程去处理业务逻辑,这样会导致业务失效

67667319212f4bb2b3ada94bd4e1596c.png

22ab640f1f9b4c148d18876f55bc0164.png

bc6ce16ea9e443fa9c6c3c780c3b18ca.png

将MainConfig注册成为一个配置类,效果等价于给它加上@Configuration注解 

6e5d981eae8d41f6a59e2b2cb00bb389.png

不激活aop的注解,也能使用声明式事务,但是就无法暴露动态代理对象,也就无法通过AopContext的形式,显示拿到当前类的动态代理对象了

a7082a29657f4c5fb72c1e3e01d772ad.png

1816f1415f0b426684d1a732c324852b.png

fdcebbde3e4a4cb0a1048131f5777993.png

6b56dc5e8c894e7586ebac97e851b6ba.png

735f8becacfa4a718ef1a3b4eda87185.png

第一个是事务转有的后置处理器,第三个是aop转有的后置处理器。

如果同时激活了事务和aop的注解,那么ioc容器中不会同时有上面两个后置处理器,aop的后置处理器会覆盖掉事务的后置处理器。

事务和普通aop的不同点是

1. 普通aop的那些增强逻辑,都是用户通过@Before,@After等注解来自定义的。这些自定义的增强逻辑,需要spring通过后置处理器如解析它们,把它们解析成一个个得Advisor。

事务的增强逻辑是内置的,也就是spring自己写的。所以Spring就自己给我们写好了一个事务专有的Advisor,并注册到了ioc容器中。

2. 普通aop的匹配,是通过AspectJ的切点表达式来进行匹配,而事务看某个方法或者类是否命中了事务专有的Advisor,是通过解析@Transactional注解

618e2a67dc3c49c4b6918178c342c28a.png

这里,spring通过配置类,给我们自动注入了一个解析@Transactional注解的bean, 

spring能自己提供,也就意味着,我们也能自己自定义一个这样的bean,并通过我们自己的配置类,将其注入到ioc容器中去

4404124c9e6547ec86d57df2b219dfdd.png

34d349ac5e0041aea79d7f42fb9e5f03.png

这里,就是Spring自己给我们写好了一个事务专有的Advisor,并注册到了ioc容器中

2c0ca0c2a9e546008db178784e2a3eac.png

5fdf23e97a87416ab39c4a52ed8fe3b5.png

34d349ac5e0041aea79d7f42fb9e5f03.png

e9bd521213384cd298fe9abcf5f0155e.png

看第49行,也设置进去了一个通知(也就是,关于事务方面的增强逻辑) 

906cee8938b64e848344c9fa33ea61d7.png

66c96d3a042c42a2bda0f8a9440a83d6.png

通过这种方式,来自动的往ioc容器中注册了一个事务专有的Advisor

ba3e254317074f5b9f52488d51b1c49f.png

小结:

1. aop是因为要解析切点表达式,来决定给那些bean生成动态代理对象。而事务就没那么复杂,只要看哪个类或者哪个类的方法上有@Transactional注解,就直接给它创建动态代理对象就好了。

2. 普通aop的解析切面,比较复杂,要把各种切面的注解解析成一个个Advisor。而事务的解析切面就简单了,Spring自己就提供了一个Advisor,都不需要去解析,直接就能拿到,拿到后事务的第一步解析切面的步骤就完成了。

3. 一共三步:解析切面,创建动态代理,调用代理方法

事务的解析切面逻辑

ddd65d831eeb45ac995f568946853d97.png

Bean后置处理器的注册与实例化

b632d8c853194bd7934fa246ce533ffd.png

540行,先通过扫描配置类,把配置类中用过通过@Bean自定义的Bean后置处理器,与通过Import注册到ioc容器中的第三方组件自己的Bean后置处理器等多种形式的处理器,通过在第543行中,来将它们全部从BeanDefinition,调用getBean方法实例化成处理器,并存入Ioc容器中的专有list中去

4d9234cc760a48c69a3cbe2d42c2fd37.png

8cd09986a2cd4661abe243891b5dd488.png

存入专有list之前,还会看这些PriorityOrdered之类的排序接口,来决定各个后置处理器存入list的先后顺序。

554368deddbc4a7da8e105a3a6385d6a.png

createBean方法中有三大步:实例化Bean ,populateBean,initializeBean。

上面就是在执行 initializeBean方法,执行初始化之前,会挨个调用每个后置处理器的前置方法,初始化后,会调用后置方法。

事务的启动流程中的一些初始化动作

b8dbed7983b24ad283e90612f82d366b.png

事务的动态代理对象生成流程

c9af1a6642d04508b7a14f26cbf5bc91.png  b500f67b30e44860882fbddc5d60d91b.png

事务的动态代理方法的调用

295f588d8f1f4440880922cbd70eaec6.png

daf2db61d8b149b3a377431615174357.png

1. 无论是普通aop还是事务,如果是走的jdk动态代理,那么就都会执行上面类的invoke方法(因为它,实现了InvocationHandler接口) 

2. 就是每次在执行上面的invoke方法时,就会把当前动态代理对象通过AopContext存入线程对象中,从而

e07abefda5a8489da4c0c665efa9a9de.png

f0019bd51e3240a59d1ec57d496d1527.png

这里才能在同一个方法内部(同一个线程),取到当前类的动态代理对象

d4630ecb6e714c8aa82cdb3af3799f5d.png

a1296d765e0140f99911996bf4fd17a0.png

e01ad646b80d4b98811c1b4b3cc83caf.png

这个就是事务专有Advisor的Advice,这个Advice用事务将目标方法包裹起来。

ef6dc3860baf4fb689f24f0889afd780.png

6a5505b09bed4a97a5c210c85766474f.png

4042c99694ce430fb4c7980f3c53c1a2.png

c055bc978b50465b88e32bd5b3afe3b0.png

b2fe15fab86a43349d1afac921085cdb.png

fe3d7e53c2404a188f5aa982937de549.png

开启事务

851862490ad84a4bb7c7e21ab550ed4a.png

激活事务

aff18f48355f486ca8e55bf76ed44896.png

doBegin方法做的事情,就是开始事务

d49d90cb1df247b082008976215d8ab2.png

无论是普通aop还是事务,都是通过上面的逻辑走的责任链。

上面这里,也就是责任链走完后,开始执行Jointpoint也就是执行真正的目标方法。

b2e709699faf4379b5b7057d03094624.png

事务的回滚

ee10f4b3548a41a88ea0319c65e4b258.png

212d5fe9021b4e1ea3b0870229377105.png

a964d4bb58ce4b2b8f60961a4d007296.png

298f56fe3f9e493292eac3e83de5b34c.png

判断是否已存在外层事务的方式

78aafa8fd91c47beacc8a6d5783e3dd8.png

内层调用suspend去挂起外部事务时,首先会将ConnectionHolder置空,然后内层调用doBegin创建新的内层事务,此时就会拿到一个新的connection,内层把这个新的connection设置到ConnectionHolder中去。

7b906fa4164f4f228f05e67f0a604c86.png

86832f4eec3c4521a220e92d534cc93e.png

这个事务同步管理器的作用,还不是特别了解

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

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

相关文章

C语言实现编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n

完整代码&#xff1a; /*编写一个函数&#xff0c;输入n为偶数时&#xff0c;调用函数求1/21/4...1/n,当输入n为奇数时&#xff0c; 调用函数1/11/3...1/n */ #include<stdio.h>//n为偶数 double Odd(int n){double sum0;//i为2&#xff0c;4&#xff0c;6....for (int …

mybatis的简单教程

整体就是mysql里存了一张表&#xff0c;然后在java程序里用mybatis把数据读出来的一个简单示例。 库 blog里有一张表 article 整个项目就是增加了这3个文件 首先是mybatis-config.xml文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE c…

【Python】20大报告生成词云

这个我其实写过一篇类似的博客&#xff0c;但是那个的文件对象是.csv&#xff0c;对应到.docx文件的话&#xff0c;就不太适用了。如下&#xff1a; Python生成词云-CSDN博客 代码&#xff1a; import jieba import os import wordcloud import numpy as np from PIL import…

多测师肖sir_高级金牌讲师_ui自动化po框架版本01

ui自动化po框架 一、po框架 1、基本介绍 &#xff08;1&#xff09;po模式是page object model的缩写&#xff08;简称&#xff1a;po或pom&#xff09; &#xff08;2&#xff09; po模式的核心思想&#xff1a;分层&#xff0c;实现耦合 实现&#xff1a;业务流程与页面元素操…

n-gram语言模型——文本生成源码

n-gram语言模型——文本生成源码 n-gram模型的基本原理 文本生成的步骤 1. 准备和分词 2. 构建n-gram模型 3. 平滑技术的应用 4. 生成文本 源码 在自然语言处理的领域中&#xff0c;n-gram语言模型是一种基础而强大的工具。它通过考虑词汇的序列来预测文本内容&#xff…

阿里大佬:DDD中Interface层、Application层的设计规范

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#xff1f…

redis主从复制+哨兵

1.主从复制 redis配置文件redis.conf master机器&#xff1a;IP 192.168.1.5 &#xff0c;端口 6379 设置配置参数 daemonize yes #bind 127.0.0.1 -::1 protected-mode no port 6379 dbfilename "dump.rdb" dir "/root/redis/my_redis_conf/dumpdir" l…

深度学习工具的安装 CUDA Anaconda

深度学习工具安装 CUDA与CUDNN的安装 查看计算机是否支持CUDA 主要参考: 一看就懂的 CUDA安装教程及Pytorch GPU版本安装教程 次要参考: cuda安装 &#xff08;windows版&#xff09; cuDNN的验证 Anaconda的包装 anaconda下载安装包国内镜像源

李峋同款的C语言动态爱心代码来了,彩色闪动,附源码

1.前言 最近一部电视剧《点燃我&#xff0c;温暖你》可火啦&#xff0c;大家纷纷在搞男主阿瑟的同款爱心代码&#xff0c;但是虽然网上有它的源码&#xff0c;但都不是 C 语言的&#xff0c;看不懂。我看了一下这个视频&#xff0c;大致分析了一下它的运行过程。用语言描述一下…

【读点论文】结构化剪枝

结构化剪枝 在一个神经网络模型中&#xff0c;通常包含卷积层、汇合层、全连接层、非线形层等基本结构&#xff0c;通过这些基本结构的堆叠&#xff0c;最终形成我们所常用的深度神经网络。 早在 1998 年&#xff0c;LeCun 等人使用少数几个基本结构组成 5 层的 LeNet-5 网络&…

Install Docker in Linux

Docker官网链接: https://docs.docker.com/ 1.确定Linux版本 新版本的Docker对Linux系统版本有一定的要求。如果Linux的发行版系统是centOS&#xff0c;安装最新版的docker需要centOS 7以上的系统。 在Docker安装帮助页面查看支持的系统版本。 Docker帮助页面:https://docs…

C语言--青蛙跳台阶【内容超级详细】

今天与大家分享一下递归的经典题目--青蛙跳台阶问题。 一.引子 电影《少年班》&#x1f357;中的老师在全国各地寻找天才少年时&#xff0c;就问了一个这样的问题&#xff0c;有20阶台阶&#xff0c;每次只能上一阶或两阶&#xff0c;总共有多少种上法&#xff1f;这个少年王…

web3 React Dapp书写订单 买入/取消操作

好 上文web3 前端dapp从redux过滤出 (我创建与别人创建&#xff09;正在执行的订单 并展示在Table上中 我们过滤出了 我创建的 与 别人创建的 且 未完成 未取消的订单数据 这边 我们起一下 ganache 环境 ganache -d然后 我们项目 发布一下智能合约 truffle migrate --reset然…

数据的属性与数据集,相似度,数据的质量,OLAP

数据的属性与数据集&#xff1a; 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sq…

[LeetCode] 5.最长回文子串

一、题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba&…

【api_fox】ApiFox简单操作

1、get和post请求的区别&#xff1f;2、接口定义时的传参格式&#xff1f;3、保存接口文档 apifox当中接口文档的设计和接口用例的执行是分开的。 1、get和post请求的区别&#xff1f; 2、接口定义时的传参格式&#xff1f; 3、保存接口文档 就生成如下的接口文档。

木板上的蚂蚁(c++题解)

题目描述 有一块木板&#xff0c;长度为 n 个 单位 。一些蚂蚁在木板上移动&#xff0c;每只蚂蚁都以 每秒一个单位 的速度移动。其中&#xff0c;一部分蚂蚁向 左 移动&#xff0c;其他蚂蚁向 右 移动。 当两只向 不同 方向移动的蚂蚁在某个点相遇时&#xff0c;它们会同时改…

移植LVGL到单片机的一个demo简单介绍

简介 背景&#xff1a; 本文使用的是主控IC为stm32f103zet6, 显示IC为ST7735s&#xff0c;它是128*160的像素&#xff0c;色深为RGB565颜色。 官方虽然说LVGL移植平台只需 64kB 闪存和 8kB RAM 就足以满足简单的用户界面。但我移植到stm32f103c8t6&#xff0c;不管怎么修改配…

Kubernetes基础(七)-Pod资源Limits与Requests

在k8s的集群环境中&#xff0c;资源的合理分配和使用非常重要。毕竟容器化要解决的问题之一就是资源的充分利用。在集群中分配资源的时候就不得不提到Limits和Requests。 1 Namespace配额 Kubernetes 是允许管理员在命名空间中指定资源 Requests 和 Limits 的&#xff0c;这一…

半小时拥有自己的ChatGPT4,高效低成本,无脑跟即可

文章目录 一、获取Key二、获取服务器三、设置端口三、安装Docker环境 一、获取Key 最简单的获取方法&#xff0c;去某宝搜 “open账号ai” 购入一个key&#xff0c;几块钱&#xff0c;有3.5、4.0&#xff0c;买3.5就行了&#xff0c;4.0太贵了。注意是购入key&#xff0c;不是…