【Spring】-编程式事务和声明式事务

spring中控制事务的方式有两种:编程式事务和声明式事务,今天我以两种事务出发,对spring中实现事务的@EnableTransactionManagement和@Transaction两个注解的底层原理进行讨论。

一、编程式事务

什么是编程式事务?

硬编码的方式实现事务,在代码中手动开始、提交和回滚事务

编程式事务实现思想是什么?

  • 配置PlatformTransactionManager事务管理器去控制事务
  • 配置TransactionDefinition设置事务属性
  • 配置TransactionTemplate控制事务

步骤和原理

1、定义数据源

2、定义一个PlatformTransactionManager 事务管理器,指定数据源。控制事务的操作(开始、提交、回滚)

3、定义TransactionDefinition 事务属性,可以配置事务属性信息

4、开启事务操作。通过调用getTransaction方法

补充:ThreadLocal中存储了datasource和connection的映射

这样当我们开启事务的时候会创建一个数据库连接,通过ThreadLocal保证线程的同步

5、执行业务操作

6、commit提交/rollback回滚事务

优缺点

优点:

以在代码中精确地控制事务的起始点、提交点和回滚点,实现更细粒度的事务管理。

缺点:

  1. 代码侵入性:编程式事务管理会将事务管理逻辑直接嵌入到业务代码中,增加了代码的复杂度和维护成本,使得业务逻辑与事务管理耦合在一起。
  2. 重复性工作:在多个业务方法中可能需要重复编写事务管理逻辑,增加了代码冗余和维护工作量。

二、声明式事务

什么是声明式事务?

通过配置的方式去管理事务,可以是xml配置文件,也可以使用spring提供的@Transactional注解

声明式事务实现思想是什么?

  • 添加@EnableTransactionManagement注解
  • 添加@Transactional注解

步骤和原理

1、启用事务管理功能-配置类上加上@EnableTransactionManagement注解

2、定义事务管理器

3、需要开启事务的目标接口/类/方法上添加@Transaction注解

4、执行业务逻辑

5、启动spring容器,获取bean执行业务逻辑

优缺点

优点:

  1. 与业务逻辑分离:声明式事务管理将事务管理逻辑从业务代码中分离出来,使得业务逻辑更清晰,降低了代码的耦合性。
  2. 配置简单:通过注解或XML配置,可以简单地定义事务的传播行为、隔离级别等属性,而无需在每个业务方法中编写重复的事务管理代码。
  3. 易于维护:由于事务管理逻辑集中在配置中,易于维护和修改,提高了代码的可读性和可维护性。
  4. 提高一致性:声明式事务管理可以确保在所有业务方法中都应用相同的事务管理策略,提高了事务管理的一致性。

缺点:

  1. 灵活性有限:声明式事务管理的灵活性相对较低,无法在运行时动态地改变事务管理策略,有一定的局限性。
  2. RPC远程调用成功,但是本地事务回滚了,RPC调用无法回滚。并且事务中有远程调用,会拉长整个事务,导致本地事务的数据库连接一致被占用,最后可能会导致数据库连接池耗尽

在阿里巴巴的开发手册中也明确标出,我们用@Transactional注解的时候要谨慎,大家在业务场景中要谨慎使用哦!


上面我已经对spring实现事务的两种方式分别进行了说明,下面我们看看它的源码,解开事务这个神秘面纱!

三、源码分析

@EnableTransactionManagement

作用是什么?

开启spring自动管理事务。在spring容器启动的时候,会拦截所有bean的创建,判断当前bean中有没有用@Transaction注解,是不是需要让spring管理事务

判断规则:

  • public方法上有没有用@Transaction注解
  • 和bean的类相关的类/接口上有没有用@Transaction注解

当满足规则之后会通过aop的方式创建代理,并且在代理中添加一个TransactionInterceptor拦截器

注意:@Transaction注解在代理对象被创建并且方法被调用时生效

@Transactional注解生效,必须确保Spring能够为目标类创建代理对象,并且方法通过代理对象调用

TransactionInterceptor拦截器的作用是什么?

拦截@Transaction方法,在方法前后添加事务额外逻辑

如果代理中还有其他拦截器,拦截器的顺序如何指定呢?

通过order()方法修改事务拦截器的执行顺序

注意:默认值是 LOWEST_PRECEDENCE = Integer.MAX_VALUE,拦截器的执行顺序是order升序

 int order() default Ordered.LOWEST_PRECEDENCE;

@Import(TransactionManagementConfigurationSelector.class)在这里的作用是什么?

@Import的作用是批量导入需要注册的类,完成bean的注册

那@Import导入了哪些类?

通过点进去TransactionManagementConfigurationSelector我们发现,里面有一个selectImports方法,这个方法的返回值是一个字符串数组,返回的字符串数组如果是正常的全限定类名才会被容器识别

通过查看selectImports方法源码,我们发现return了两个类-AutoProxyRegistrar、ProxyTransactionManageMentConfiguration,也就是说Import导入了这两个类

  1. AutoProxyRegistrar:启用spring aop功能,创建代理
  2. ProxyTransactionManageMentConfiguration:在aop中添加事务拦截器

①、AutoProxyRegistrar

点进源码,我们看registerBeanDefinitions这个方法,看过spring容器启动流程的小伙伴会发现,其中流程就会调用这个方法,AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)作用是向spring容器注册一个自动代理创建器,从而启用AOP代理的功能

在方法内部会导入InfrastructureAdvisorAutoProxyCreator类,给spring 容器中注册了一个后置处理器-BeanPostProcessor,拦截所有bean的创建并将符合规则的bean创建代理,对类进行增强

在生命周期阶段,创建bean的时候只有需要增强,就会调用BeanPostProcessor的after进行增强

②、ProxyTransactionManageMentConfiguration

配置类,一般是提供加了@Bean的一些方法。注册了一个事务拦截器TransactionInterceptor

总:通过对上面两个导入的类的源码分析我们明确了他们的作用,我们使用@Transaction标注的bean会通过AutoProxyRegistrar去启用aop功能,通过ProxyTransactionManagementConfiguration在aop中添加事务拦截器从而实现事务管理

如果有想要交流的内容欢迎在评论区进行留言,如果这篇文档受到了您的喜欢那就留下你点赞+收藏+评论脚印支持一下博主~

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

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

相关文章

Adobe将Sora、Runway、Pika,集成在PR中

4月15日晚,全球多媒体巨头Adobe在官网宣布,将OpenAI的Sora、Pika 、Runway等著名第三方文生视频模型,集成在视频剪辑软件Premiere Pro中(简称“PR”)。 同时,Adob也会将自身研发的Firefly系列模型包括视频…

【Python】高级进阶(专版提升3)

Python 1 程序结构1.1 模块 Module1.1.1 定义1.1.2 作用1.1.3 导入1.1.3.1 import1.1.3.2 from import 1.1.4 模块变量1.1.5 加载过程1.1.6 分类 1.2 包package1.2.1 定义1.2.2 作用1.2.3 导入1.1.3.1 import1.1.3.2 from import 2 异常处理Error2.1 异常2.2 处理 3 迭代3.1 可…

Three.js 入门——核心概念和坐标系理解

Three.js 是什么? 一个封装了 WebGL 的库,简化 WebGL 的使用 WebGL vs OpenGL OpenGL 主要被认为是一种 API(应用程序编程接口),它为我们提供了大量可用于操作图形和图像的函数,主要用 C语言编写的。 然…

python辅助QQ登入

python辅助QQ登入 import pyautogui import time import random from pyautogui import ImageNotFoundException# 生成随机等待时间,范围在1到3秒之间 random_time random.uniform(1, 3)def find_and_click(image_path, moveFalse, execute_nextTrue):try:image_l…

【QT学习】7.事件,把文本显示在页面中(文本可变),鼠标指针切换,鼠标左键右键按下,qt设置背景样式

0.创建项目,事件的创建 1.事件的位置 2.这就是多态,子类重写父类函数,子类调用子类函数,也可以调用父类函数。但同函数名 1.要求:文本显示在页面中(文本可变) 1.文本显示在页面的核心代码 主要步…

DRF requets源码分析

【四】requets源码分析 【1】查看request传递的数据 (1)视图层 编写传输数据的接口查看request方法的参数 class BookAPIView(APIView):def get(self, request, *args, **kwargs):return Response({body: request.body, data: request.data, post: r…

【Web】DASCTF X GFCTF 2022十月挑战赛题解

目录 EasyPOP hade_waibo EasyLove BlogSystem EasyPOP 先读hint.php sorry.__destruct -> secret_code::secret() exp: $anew sorry(); $bnew secret_code(); $a->password"suibian"; $a->name"jay"; echo serialize($a); 真暗号啊&…

web项目中jsp页面不识别el表达式

如果使用el表达式出现下图问题 ** 解决办法 ** 这是因为maven创建项目时&#xff0c;web.xml头部声明默认是2.3&#xff0c;这个默认jsp关闭el表达式 修改web.xml文件开头的web-app的版本 <?xml version"1.0" encoding"UTF-8"?> <web-app x…

Python爬取猫眼电影票房 + 数据可视化

目录 主角查看与分析 爬取可视化分析猫眼电影上座率前10分析猫眼电影票房场均人次前10分析猫眼电影票票房占比分析 主角查看与分析 爬取 对猫眼电影票房进行爬取&#xff0c;首先我们打开猫眼 接着我们想要进行数据抓包&#xff0c;就要看网站的具体内容&#xff0c;通过按F12…

Postman之安装

Postman工具之介绍与安装 Postman是什么&#xff1f;Postman有几种安装方式&#xff1f; Postman是什么&#xff1f; postman是一款http客户端的模拟器&#xff0c;它可以模拟发出各种各样的网络请求&#xff0c;用于接口测试。 Postman有几种安装方式&#xff1f; 两种&…

4.17 网络编程

思维导图 select实现TCP并发服务器 #include <myhead.h> #define SER_IP "192.168.125.26" #define SER_PORT 8888int main(int argc, const char *argv[]) {int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){perror("socket error");return -1…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 小区物业管理系统 的设计与实现

一.项目介绍 系统分为管理员 和 业主 两块&#xff1a; 管理员点击进入到系统操作界面&#xff0c;可以对首页、业主信息管理、管理员信息管理、 楼栋和房屋信息管理、物业费管理、地下停车位管理、公告信息管理、报修信息管理、 投诉管理以及个人信息等功能模块 …

libftdi1学习笔记 5 - SPI Nor Flash

目录 1. 初始化 2. CS控制例子 3. 读ID 3.1 制造商 3.2 容量大小 3.3 设置IO类型 3.3.1 setQSPIWinbond 3.3.2 setQSPIMxic 3.3.3 setQSPIMicrochip 3.3.4 setQSPIMicron 4. 写保护 5. 等待空闲 6. 擦除扇区 7. 页编程 8. 页读 9. 写 10. 读 11. 验证 基于M…

cesium加载高层级离线影像地图瓦片(天地图、19级Arcgis)

实际加载效果如图&#xff1a; 1、下载离线地图瓦片方式&#xff08;多种任选其一&#xff0c;个人倾向于Qgis工具&#xff09;&#xff1a; 方式1、采用第三方下载工具如&#xff1a;91卫图、水经注、全能电子地图下载器、bigemap等等。&#xff08;这些有的下载层级不够&…

Spring Boot:Web应用开发之登录与退出的实现

Spring Boot 前言实现登录功能配置拦截器 实现退出功能 前言 登录与退出功能作为 Web 应用中的基础且重要的组成部分&#xff0c;直接关系到用户的安全和隐私保护。通过实现登录与退出功能&#xff0c;可以对用户的身份进行验证和授权&#xff0c;确保只有合法的用户才能访问特…

Qwen1.5大语言模型微调实践

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的兴起和广泛应用&#xff0c;为自然语言处理&#xff08;NLP&#xff09;带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者&#xff0c;不仅拥有强大的语言生成和理…

vue3【详解】选项式 API 实现逻辑复用

抽离逻辑代码到一个函数函数命名约定为 useXxxx格式 ( React Hooks 也是 )在 setup 中引用 useXxx 函数 演示代码&#xff1a;实时获取鼠标的坐标 逻辑封装 useMousePosition.js // 导入 ref, onMounted, onUnmounted import { ref, onMounted, onUnmounted } from "vue…

锐捷云桌面的安装

按下 <DEL> 键进入 BIOS setup 界面&#xff08;初始密码为 admin &#xff09;。 输入密码之后就进入 BIOS 的 Main 界面 设置服务器 BMC IP 地址。 a 云服务器启动后&#xff0c;在 BIOS 的主页面&#xff0c;把光标移到 [Server Mgmt] 项。 b 选择 [BMC Network C…

游戏前摇后摇Q闪E闪QE闪QA等操作

备注&#xff1a;未经博主允许禁止转载 个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_w…

基于Springboot的社区防疫物资申报系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的社区防疫物资申报系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…