【Spring事务底层实现原理】
@Transactional注解
Spring使用了TransactionInterceptor拦截器,该拦截器主要负责事务的管理,包括开启、提交、回滚等操作。当在方法上添加@Transactional注解时,Spring会在AOP框架中对该方法进行拦截,TransactionInterceptor会在该方法执行前后,对事务进行切面处理,Spring会基于该类生成一个代理对象,把这个代理对象作为bean。当调用这个代理对象的方法时,如果有事务处理,则会先关闭事务的自动功能,然后执行方法的具体业务逻辑,如果业务逻辑没有异常,那么代理逻辑就会直接提交,如果出现任何异常,那么直接进行回滚操作。
事务管理器
Spring还提供了多种事务管理器,包括JDBC事务管理器、Hibernate事务管理器、JTA事务管理器等等,可以满足不同数据访问层的需求。事务通知是Spring事务机制中的一个重要组成部分,主要用于判断哪些方法需要被事务管理,以及如何管理事务。
Spring事务底层实现原理
应用启动时会创建一个代理类,把事务逻辑织入到代理类中,然后用代理类替代目标类,并放入上下文容器中。当实际调用目标类的事务方法时,被代理类拦截,先执行拦截器中的事务逻辑,再执行目标类的业务逻辑,最后处理异常回滚和提交。这样就能实现简单、方便、可控的事务管理。
示例代码
这里给出一个简单的示例代码:
定义一个接口,包含需要进行事务管理的方法:
public interface UserService {void addUser(User user);void deleteUser(String id);void updateUser(User user);User getUser(String id);
}
实现这个接口的目标类:
public class UserServiceImpl implements UserService {@Overridepublic void addUser(User user) {//添加用户的业务逻辑}@Overridepublic void deleteUser(String id) {//删除用户的业务逻辑}@Overridepublic void updateUser(User user) {//更新用户的业务逻辑}@Overridepublic User getUser(String id) {//查询用户的业务逻辑return null;}
}
定义一个事务拦截器类:
/*** TransactionInterceptor 是一个实现了 MethodInterceptor 接口的拦截器类*/
public class TransactionInterceptor implements MethodInterceptor {/*** TransactionManager 对象,用于管理事务*/private TransactionManager txManager;/*** 用于注入 TransactionManager 对象* @param txManager TransactionManager 对象*/public void setTxManager(TransactionManager txManager) {this.txManager = txManager;}/*** 实现 MethodInterceptor 接口的 invoke 方法,用于拦截指定方法* @param invocation MethodInvocation 对象,用于获取被拦截的方法及其参数* @return 执行方法的返回结果* @throws Throwable 抛出异常*/@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {Object result;try {// 开启事务txManager.start();// 执行被拦截的方法,并获取方法执行的返回结果result = invocation.proceed(); // 提交事务txManager.commit();} catch (Exception e) {// 回滚事务txManager.rollback();throw e;}return result;}
}
定义一个上下文容器类:
public class ApplicationContext {private Map<String, Object> beanMap = new HashMap<>(); // 用于存放bean的map// 注册beanpublic void registerBean(String name, Object bean) {beanMap.put(name, bean); // 将bean存放到map中}// 获取beanpublic Object getBean(String name) {Object bean = beanMap.get(name); // 从map中获取beanif (bean instanceof Advised) { // 如果bean是Advised类型,说明使用了AOPreturn ((Advised)bean).getTargetSource().getTarget(); // 返回目标对象}return bean; // 返回原始对象}
}
在应用启动时,创建一个代理工厂类,使用上述事务拦截器对目标类进行代理:
/*** 代理工厂类,用于创建代理对象*/
public class ProxyFactory {/*** 创建代理对象* @param target 目标对象,需要被代理的对象* @param interceptor 事务拦截器,代理对象需要加入该拦截器* @return 返回代理对象*/public static Object createProxy(Object target, TransactionInterceptor interceptor) {DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();AdvisedSupport advisedSupport = new AdvisedSupport();advisedSupport.setTarget(target); // 设置目标对象advisedSupport.addAdvice(interceptor); // 添加事务拦截器return proxyFactory.createAopProxy(advisedSupport).getProxy(); // 创建代理对象并返回}
}
然后在应用启动时,创建容器并注册代理类:
public class Main {public static void main(String[] args) {ApplicationContext context = new ApplicationContext();UserService target = new UserServiceImpl(); //创建目标类TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTxManager(new TransactionManager()); //设置事务管理器UserService proxy = (UserService) ProxyFactory.createProxy(target, interceptor); //创建代理类context.registerBean("userService", proxy); //注册代理类到上下文容器中//使用代理类进行业务操作User user = new User();context.getBean("userService").addUser(user);}
}
这样,当执行代理类的方法时,就会先执行事务拦截器中的事务逻辑,再执行目标类的业务逻辑。如果出现异常,会进行回滚。这样就实现了简单、方便、可控的事务管理。
相关文章:
【Spring事务底层实现原理】
Transactional注解 Spring使用了TransactionInterceptor拦截器,该拦截器主要负责事务的管理,包括开启、提交、回滚等操作。当在方法上添加Transactional注解时,Spring会在AOP框架中对该方法进行拦截,TransactionInterceptor会在该…...
docker快速安装redis,mysql,minio,nacos等常用软件【持续更新】
redis ①拉取镜像 docker pull redis② 创建容器 docker run -d --name redis --restartalways -p 6379:6379 redis --requirepass "PASSWORD"–requirepass “输入你的redis密码” nacos ①:docker拉取镜像 docker pull nacos/nacos-server:1.2.0②…...
SCRUM产品负责人(CSPO)认证培训课程
课程简介 Scrum是目前运用最为广泛的敏捷开发方法,是一个轻量级的项目管理和产品研发管理框架。产品负责人是Scrum的三个角色之一,产品负责人在Scrum产品开发当中扮演舵手的角色,他决定产品的愿景、路线图以及投资回报,他需要回答…...
python连接mysql数据库的练习
一、导入pandas内置的sqlite3模块,连接的信息:ip地址是本机, 端口号port 是3306, 用户user是root, 密码password是123456, 数据库database是lambda-xiaozhang import pymysql# 打开数据库连接,参数1:主机名或IP;参数…...
扩散模型在图像生成中的应用:从真实样例到逼真图像的奇妙转变
一、扩散模型 扩散模型的起源可以追溯到热力学中的扩散过程。热力学中的扩散过程是指物质从高浓度往低浓度的地方流动,最终达到一种动态的平衡。这个过程就是一个扩散过程。 在深度学习领域中,扩散模型(diffusion models)是深度生…...
Windows 打包 Docker 提示环境错误: no DOCKER_HOST environment variable
这个问题应该还是比较常见的。 [ERROR] Failed to execute goal io.fabric8:docker-maven-plugin:0.40.2:build (default) on project mq-service: Execution default of goal io.fabric8:docker-maven-plugin:0.40.2:build failed: No <dockerHost> given, no DOCKER_H…...
2023.9.8 基于传输层协议 UDP 和 TCP 编写网络通信程序
目录 UDP 基于 UDP 编写网络通信程序 服务器代码 客户端代码 TCP 基于 TCP 编写网络通信程序 服务器代码 客户端代码 IDEA 打开 支持多客户端模式 UDP 特点: 无连接性:发送端和接收端不需要建立连接也可相互通信,且每个 UDP 数据包都…...
单例模式,适用于对象唯一的情景(设计模式与开发实践 P4)
文章目录 单例模式实现代理单例惰性单例 上一章后续的内容是关于 JS 函数闭包的,考虑很多读者已经有了闭包基础或者希望通过实战理解,遂跳过上一章直接开始设计模式篇~ 需要注意的是,代码部分仅供参考,主要关注的内容是…...
C语言实现三子棋游戏(详解)
目录 引言: 1.游戏规则: 2.实现步骤: 2.1实现菜单: 2.2创建棋盘并初始化: 2.3绘制棋盘: 2.4玩家落子: 2.5电脑落子: 2.6判断胜负: 3.源码: 结语&…...
javaee之黑马乐优商城3
异步查询工具axios(儿所以时) vue官方推荐的ajax请求框架 新增品牌页面 如何找到上面这个页面 下面这个页面里面的新增商品弹窗 上面就是请求路径与请求方式 那么请求参数是什么? brand对象,外加商品分类的id数组cids (这里其实不止就是添加…...
Pytorch intermediate(二) ResNet
实现了残差网络,残差网络结构。代码比之前复杂很多 conv3x3:将输入数据进行一次卷积,将数据转换成为,残差块需要的shape大小 ResidualBlock:残差块,也是所谓的恒等块。为什么被称为恒等块,大概…...
【2023集创赛】加速科技杯作品:高光响应的二硫化铼光电探测器
本文为2023年第七届全国大学生集成电路创新创业大赛(“集创赛”)加速科技杯西北赛区二等奖作品分享,参加极术社区的【有奖征集】分享你的2023集创赛作品,秀出作品风采,分享2023集创赛作品扩大影响力,更有丰…...
编写postcss插件,全局css文件px转vw
跟目录下创建plugins文件夹,创建postcss-px-to-viewport.ts文件 文件内代码: // postcss 的插件 vite内置了postCss插件 无需安装 import { Plugin } from postcss;interface Options {viewportWidth: number }const Options {viewportWidth: 375, // …...
精品SpringCloud的B2C模式在线学习网微服务分布式
《[含文档PPT源码等]精品基于SpringCloud实现的B2C模式在线学习网站-微服务-分布式》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等 软件开发环境及开发工具: 开发语言:Java 框架:springcloud JDK版本…...
解决vue项目导出当前页Table为Excel
解决vue项目中导出当前页表格为Excel表格的方案 用到的技术: Vue2Element-uifile-saverxlsx 1、创建vue项目,安装element-ui 2、创建一个组件,组件内放入表格,和导出按钮 <template><div><!-- 导出的按钮 -->…...
C++设计模式_04_Strategy 策略模式
接上篇,本篇将会介绍C设计模式中的Strategy 策略模式,和上篇模板方法Template Method一样,仍属于“组件协作”模式,它与Template Method有着异曲同工之妙。 文章目录 1. 动机( Motivation)2. 代码演示Stra…...
目标检测YOLO实战应用案例100讲-基于YOLOv3多模块融合的遥感目标检测(中)
目录 2.2.3 YOLO 2.3 目标检测算法分析 2.3.1 目标检测结果评价指标...
element 表格fixed列高度无法100%
下文提到的滚动条皆为横向滚动条错误方法(旧方法,点击查看旧博客) 一下代码虽然能解决fixed列高度无法100%问题,但是会出现fixed列下面的滚动条无法被点击的问题(被fixed列遮挡),所以该方法并不…...
【接口自动化测试】Eolink Apilkit 安装部署,支持 Windows、Mac、Linux 等系统
Eolink Apikit 有三种客户端,可以依据自己的情况选择。三种客户端的数据是共用的,因此可以随时切换不同的客户端。 我们推荐使用新推出的 Apikit PC 客户端,PC 端拥有线上产品所有的功能,并且针对本地测试、自动化测试以及使用体…...
解决sass问题:npm ERR! node-sass@9.0.0 postinstall: `node scripts/build.js`
目录 一、遇到问题 解决办法 二、 再次遇到问题 解决办法 题外话 一、遇到问题 1.运行这个项目的适合,遇到了没有sass的问题 解决办法 然后就用命令下载sass npm install node-sass 二、 再次遇到问题 2.下载sass的时候又发现了一个这样的问题 npm ER…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
上位机知识篇---Flask框架实现Web服务
本文将简单介绍Web 服务与前端显示部分,它们基于Flask 框架和HTML/CSS/JavaScript实现,主要负责将实时视频流和检测结果通过网页展示,并提供交互式状态监控。以下是详细技术解析: 一、Flask Web 服务架构 1. 核心路由设计 app.…...
【从零学习JVM|第二篇】字节码文件
前言: 通过了解字节码文件可以帮助我们更容易的理解JVM的工作原理,所以接下来,我们来介绍一下字节码文件。 目录 前言: 正确的打开字节码文件 字节码文件组成 1. 魔数(Magic Number) 2. 版本号&…...
word操作(持续更新)
1、图片前面(无间隔格式),有像标题标记一样的黑点 word段落左边的黑色小方块小黑点是什么(段落的换行和分页属性)_哔哩哔哩_bilibili...
LeetCode 1356.根据数字二进制下1的数目排序
题目: 给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。 如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。 请你返回排序后的数组。 提示: 1 < arr.length < 5000…...
基于深度强化学习的智能机器人导航系统
前言 随着人工智能技术的飞速发展,机器人在日常生活和工业生产中的应用越来越广泛。其中,机器人导航技术是实现机器人自主移动的关键。传统的导航方法依赖于预设的地图和路径规划算法,但在复杂的动态环境中,这些方法往往难以适应。…...
