Spring事务的源码底层实现

文章目录

  • 事务
    • 理论执行过程
    • @EnableTransactionManagement
    • 底层实现



事务

在线流程图

在这里插入图片描述



理论执行过程

通过事务管理器创建一个连接对象connection1设置事务隔离级别、是否只读等conn1.autocommit(false)将conn1存入ThreadLocal中Map<DataSource,Connection>执行目标方法、多条sql:target.method()挂起 ---> con1通过事务管理器创建一个连接对象connection2设置事务隔离级别、是否只读等conn2.autocommit(false)将conn2存入ThreadLocal中Map<DataSource,Connection>执行目标方法、多条sql:target.method()根据执行结果进行事务提交/回滚     commit()-->回滚标记true-->rollback()    rollback()-->异常匹配-->commmit()恢复 ---> con1 ---> ThreadLocal Map根据执行结果进行事务提交/ 回滚   commit() ---> 回滚标记true  ---> rollback()   rollback()-->异常匹配-->commmit()



@EnableTransactionManagement

@EnableTransactionManagement内,其实就是导入了一个TransactionManagementConfigurationSelector

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {...
}

而在TransactionManagementConfigurationSelector类它其实是一个ImportSelector类型的,在该类的selectImports()方法中主要就是导入了两个类

protected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:// 默认是PROXY,这里会往Spring容器中导入两个类return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:// 表示不用动态代理技术,用ASPECTJ技术,比较麻烦了return new String[] {determineTransactionAspectClass()};default:return null;}
}



  • AutoProxyRegistrar

    简单理解为就是一个BeanPostProcessor,进行AOP的入口

    此类会往Spring容器中添加一个InfrastructureAdvisorAutoProxyCreator的Bean,此类就和进行AOP操作时导入的AnnotationAwareAspectJAutoProxyCreator类一样,他们两个类都是AbstractAutoProxyCreator的子类,也就是说都是一个BeanPostProcessor

    InfrastructureAdvisorAutoProxyCreator它不会去解析@Aspectj切面类,但是它的父类会获取Spring容器中所有的Advisor

    在这里插入图片描述


  • ProxyTransactionManagementConfiguration

    简单理解为

    这个配置类使用@Bean注解往Spring容器中添加了三个bean

    • BeanFactoryTransactionAttributeSourceAdvisor

      它就是一个Advisor,我们知道它是由advice+Pointcut组成。在创建该bean时,会进行依赖注入,在方法形参中注入下面两个类型的bean

    • TransactionAttributeSource

      它和pointcut有关系,Pointcut会用到该类,我们可以把它简单理解为就是一个工具类,它会去解析方法上写的@Transactional注解信息

    • TransactionInterceptor

      就是advice执行链,也就是Interceptor



总结:

  1. 我们要事务要使用AOP这个功能,那么就一定是需要一个BeanPostProcessor来作为启动入口,也就是AutoProxyRegistrar类引入的InfrastructureAdvisorAutoProxyCreator

  2. 在创建普通bean时,在实例化后会取出所有的Advisor和当前bean进行匹配。

    要经过advisor中的Pointcut去进行类和方法匹配,只要是匹配上了就表示当前bean是需要创建一个代理对象的。

    这里也就用上了BeanFactoryTransactionAttributeSourceAdvisorTransactionAttributeSource两个类

  3. 代理对象到时候执行目标方式之前,会经过Pointcut匹配,再到Interceptor链,会进行事务相关的处理,再去调用目标方法。

    这里也就用上了TransactionInterceptor

至此,@EnableTransactionManagement注解的总体功能就是这样,剩下的只是各个类中的详细实现



底层实现

前置知识:

  1. 在创建各个bean时,会在实例化后执行BeanPostProcessor中的后置方法
  2. 在这个过程中会进行AOP操作,把Spring容器中所有的Advisor类型的bean找出来,并和当前正在创建的bean进行匹配
  3. 将匹配筛选后的Advisor集合、当前创建的bean 使用ProxyFactory创建一个代理对象。
  4. 当代理对象调用目标方法时,就会去遍历ProxyFactory中添加的所有Advisor,执行匹配成功的Interceptor链中的各个invoke()方法 --> proceed()方法

当我们使用Spring事务这个功能,在方法上加了@Transactional注解,并通过代理对象调用该方法时,就会最开始进入到Interceptor的invoke()方法中。也就是TransactionInterceptor.invoke(MethodInvocation invocation)方法



最核心的代码就是下面这一段

// 下面几个关键方法就不粘贴源码了,各位小伙伴自行根据最上方流程图去跟源码
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {// 如果有必要就创建事务,这里就涉及到事务传播机制的实现了// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);Object retVal;try {// 执行下一个Interceptor或被代理对象中的方法retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {// 抛异常了,则回滚事务,或者completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {cleanupTransactionInfo(txInfo);}...// 提交事务commitTransactionAfterReturning(txInfo);return retVal;
}



源码中的小记录:

// Spring源码中数据库连接对象的状态转变
Connection --> ConnectionHolder --> DataSourceTransactionObject(常见)---> SuspendedResourcesHolder(挂起) --> TransactionStatus ---> TransactionInfo



Spring事务的其他操作:

@Component
public class UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate UserService userService;@Transactionalpublic void test(){System.out.println("test()...");jdbcTemplate.execute("insert into m_test VALUES(2,100)");userService.a();// 自己添加多个同步器TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void suspend() {// 当前事务挂起时执行TransactionSynchronization.super.suspend();}@Overridepublic void resume() {// 当前事务恢复时执行TransactionSynchronization.super.resume();}@Overridepublic void beforeCommit(boolean readOnly) {// 当前事务提交前执行TransactionSynchronization.super.beforeCommit(readOnly);}@Overridepublic void beforeCompletion() {// 当前事务完成前执行,提交或回滚都算是事务完成TransactionSynchronization.super.beforeCompletion();}@Overridepublic void afterCommit() {// 当前事务提交后执行TransactionSynchronization.super.afterCommit();}@Overridepublic void afterCompletion(int status) {// 当前事务完成后执行TransactionSynchronization.super.afterCompletion(status);}});// 捕捉一个异常,使用一个自定义的数据友好返回前端,但是该方法前面执行的sql还是需要回滚try {throw new NullPointerException();} catch (NullPointerException e) {// 事务提交时会判断RollbackOnly,再不提交转而进行回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();return new Result();}}@Transactional()public void a(){System.out.println("a()...");jdbcTemplate.execute("insert into m_test VALUES(3,300)");}}

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

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

相关文章

Session会话与请求域的区别

session会话和请求域&#xff08;也称为request域&#xff09;都是用于存储和管理用户特定信息的重要概念&#xff0c;但它们在作用范围和生命周期上有显著的不同。 请求域 (Request Domain) 作用范围&#xff1a;请求域是面向单次请求的。每次HTTP请求都会创建一个新的request…

Java中的程序异常处理介绍

一、异常处理机制 Java提供了更加优秀的解决办法&#xff1a;异常处理机制。 异常处理机制能让程序在异常发生时&#xff0c;按照代码的预先设定的异常处理逻辑&#xff0c;针对性地处理异常&#xff0c;让程序尽最大可能恢复正常并继续执行&#xff0c;且保持代码的清晰。 Ja…

算法刷题日志 —— 数组和位运算

文章目录 [461. 汉明距离](https://leetcode.cn/problems/hamming-distance/submissions/542447020/)[448. 找到所有数组中消失的数字](https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/submissions/)[136. 只出现一次的数字](https://leetcode.cn/pro…

最长回文串

描述&#xff1a; 最长回文串 思路&#xff1a; 统计每个字母出现次数&#xff0c;如果是偶数&#xff0c;ret x;如果是存在奇数的话&#xff0c;就可以放在中间&#xff0c;ret 1. 代码&#xff1a; class Solution { public:int hash[200];int longestPalindrome(str…

AI智能修复视频,垃圾画质也变高清 HD——牛小影

很多时候&#xff0c;从网上下载的视频或监控视频都是模糊的。有什么方法或者软件可以让哪些模糊的视频恢复清晰吗&#xff1f;今天就给大家推荐一个可以使模糊的视频变清晰的软件。 我们都知道用PS或者一些修复工具可以修复模糊的图片&#xff0c;但是很多人不知道的是视频也可…

构建LangChain应用程序的示例代码:46、使用 Meta-Prompt 构建自我改进代理的 LangChain 实现

Meta-Prompt 实现 摘要&#xff1a; 本文介绍了 Noah Goodman 提出的 Meta-Prompt 方法的 LangChain 实现&#xff0c;该方法用于构建能够自我反思和改进的智能代理。 核心思想&#xff1a; Meta-Prompt 的核心思想是促使代理反思自己的性能&#xff0c;并修改自己的指令。…

上班族要怎么挑选智能猫砂盆?今年最受欢迎的牌子都在这里了!

对于上班族来说&#xff0c;猫砂盆里的猫屎到底该如何是好&#xff0c;放到下班回来再铲&#xff0c;猫砂的臭味早就飘满屋子&#xff0c;想立刻铲掉吧&#xff0c;班不要上啦&#xff1f;可是不铲就会生细菌&#xff0c;谁也不想花个几千块去给猫咪看病吧&#xff0c;谁不希望…

Linux:进程和计划任务管理

目录 一、程序和进程 1.1、程序 1.2、进程 1.3、线程 1.4、协程 二、查看进程相关命令 2.1、ps命令&#xff08;查看静态的进程统计信息&#xff09; 第一行为列表标题&#xff0c;其中各字段的含义描述如下 2.2、top命令&#xff08;查看进程动态信息&#xff09; 2…

商城积分系统的设计方案(上)-- 需求分析

一、背景 用户在参与公司的促销活动&#xff0c;比如邀请用户下单支付&#xff0c;可以获得虚拟货币。它可以用于解锁学习课程。 商品在定价的时候&#xff0c;需支持虚拟货币&#xff0c;用户在购买该商品的时候&#xff0c;可使用虚拟货币进行支付。 在电商体系中&#xf…

PID算法介绍以及代码实现过程说明

写在正文之前 在上一篇文章就说会在这两天会基于PID写一个文章&#xff0c;这里的原理部分值得大家都看一下&#xff0c;代码部分的实现是基于python的&#xff0c;但是对于使用其他编程语言的朋友&#xff0c;由于我写的很通俗易懂&#xff0c;所以也值得借鉴。 一、PID算法…

linux基于wifi,Xshell的远程连接

最近有个比赛&#xff0c;要使用ros小车但是系统是ubuntu20.04无桌面系统刚开始接触linux的我啥都不会&#xff0c;就一个简单的连接wifi都搞了3天才搞通。再此进行一个总结。参考博客原文链接&#xff1a;https://blog.csdn.net/qq_51491920/article/details/126221940 一、什…

短说V4.1.5及PC端V3.1.4正式版发布公告

Hi 大家好&#xff0c; 我是给你们带来惊喜的运营小番茄。 本期更新为短说 4.1.5和PC端3.1.4的正式版。 本次修复上个版本中的问题和功能优化&#xff0c;以及新增了如下功能&#xff1a; PC端支持发布秀米帖&#xff0c;可支持部分秀米格式&#xff1b;后台管理类消息新增…

【秋招刷题打卡】Day03-二分系列之-二分答案

Day03-二分系列之-二分答案 给大家推荐一下咱们的 陪伴打卡小屋 知识星球啦&#xff0c;详细介绍 >笔试刷题陪伴小屋-打卡赢价值丰厚奖励 < ⏰小屋将在每日上午发放打卡题目&#xff0c;包括&#xff1a; 一道该算法的模版题 (主要以力扣&#xff0c;牛客&#xff0c;…

43 mysql insert select 的实现

前言 我们这里 来探讨一下 insert into $fields select $fields from $table; 的相关实现, 然后 大致来看一下 为什么 他能这么快 按照 我的思考, 应该里里面有 批量插入才对, 但是 调试结果 发现令我有一些意外 呵呵 果然 只有调试才是唯一的真理 测试数据表如下 CREATE…

数字社交的领航者:解析Facebook的引领作用

在当今数字化社会中&#xff0c;社交网络已经成为了人们日常生活不可或缺的一部分。而在众多社交平台中&#xff0c;Facebook凭借其巨大的用户基础和创新的技术应用&#xff0c;被公认为数字社交领域的领航者之一。本文将深入解析Facebook在数字社交中的引领作用&#xff0c;探…

这三款工具很好用,赶快试试

FileZilla FileZilla是一款免费开源的FTP软件&#xff0c;分为客户端版本和服务器版本&#xff0c;具备所有的FTP软件功能。它是一个快速、可信赖的FTP客户端以及服务器端开放源代码程序&#xff0c;具有多种特色和直觉的界面。FileZilla客户端版是一个方便高效的FTP客户端工具…

第一后裔The First Descendant开服时间、配置要求一览

第一后裔是一款采用虚幻5引擎打造的第三人称合作射击动作RPG&#xff0c;玩家将化身为一名继承者&#xff0c;通过各种任务和故事不断成长&#xff0c;为守护人类与对抗侵略者战斗。该作即将上线&#xff0c;为了不让玩家们错过这款精彩的游戏&#xff0c;本文整理了第一后裔上…

测评:【AI办公】版本更迭与AI加持下的最新ONLYOFFICE桌面编辑器8.1

你是否还在为没有一款合适的在线桌面编辑器而苦恼&#xff1f;你是否还在因为办公软件的选择过少而只能使用WPS或者office&#xff1f;随着办公需求的不断变化和发展&#xff0c;办公软件也在不断更新和改进。ONLYOFFICE 作为一款全功能办公软件&#xff0c;一直致力于为用户提…

2024年全国青少年信息素养大赛图形化编程复赛样题_6547网

第 1 题 问答题 【编程实现】 按空格键随机切换背景&#xff0c;让背景对应的角色造型显示在舞台上。 【具体要求】 对角色编程&#xff0c;当按下空格键时&#xff0c;背景随机切换&#xff1b; 角色切换成对应的造型显示在舞台上&#xff1b; 角色说“我是”和它的造…

帮助你简易起步一个BLOG(博客搭建)项目

Blog项目 后端项目结构1. 项目初始化2. 详细步骤3.postman测试 前端1. 项目初始化2. 详细步骤 本章节是为了帮助你起步一个完整的前后端分离项目。 前端技术栈&#xff1a; react、vite、mantine、tailwind CSS、zustand、rxjs、threejs 后端技术栈&#xff1a;nodemon、nodej…