声明式事务的传播机制是解决多个事务方法嵌套调用时,事务如何创建、复用、挂起或隔离的核心逻辑。它的实现依赖于事务管理器、事务状态管理、线程上下文绑定等组件的协同,本质是通过一套 “规则判断 + 状态维护” 的逻辑,在方法调用时动态决定事务的行为。

一、传播机制的核心目标

当一个带有@Transactional的方法 A 调用另一个带有@Transactional的方法 B 时,需要解决:

  • 方法 B 是否复用方法 A 的事务?
  • 方法 B 是否需要新建事务,同时挂起方法 A 的事务?
  • 如果方法 A 没有事务,方法 B 是否必须报错(如 MANDATORY)?

传播机制就是通过预定义的规则(如 REQUIRED、REQUIRES_NEW 等),自动处理这些场景,避免手动控制事务的繁琐。

二、实现的核心组件

传播机制的实现依赖于 Spring 事务体系中的几个核心组件,它们的协作是关键:

  1. TransactionDefinition
    定义了事务的 “元信息”,包括:

    • 传播行为(propagationBehavior):如 REQUIRED、REQUIRES_NEW 等;
    • 隔离级别、超时时间、是否只读等。
      每个@Transactional注解的方法都会被解析为一个TransactionDefinition对象,作为传播机制的判断依据。
  2. PlatformTransactionManager
    事务管理器的顶层接口,其中getTransaction(TransactionDefinition definition)方法是传播机制的 “决策核心”—— 它根据当前线程的事务状态和TransactionDefinition中的传播行为,决定如何处理事务(创建、复用、挂起等)。

  3. TransactionStatus
    维护事务的实时状态,包括:

    • 是否是新创建的事务(isNewTransaction ());
    • 是否挂起了外层事务(如果有);
    • 事务是否被标记为回滚(isRollbackOnly ())。
      它是事务管理器和后续操作(提交 / 回滚)的 “状态凭证”。
  4. TransactionSynchronizationManager
    通过ThreadLocal存储当前线程的事务上下文(如当前事务的连接、挂起的事务等),让事务管理器能感知到 “当前线程是否已有事务”。

  5. TransactionInterceptor(AOP 拦截器)
    作为 AOP 的环绕通知,在目标方法执行前触发事务管理器的getTransaction()方法(决策传播行为),在方法执行后根据结果触发commit()rollback()

三、传播机制的实现流程

以 “方法 A 调用方法 B” 为例,拆解传播机制的核心步骤:

步骤 1:AOP 拦截与元信息解析

当方法 B 被调用时,TransactionInterceptor先拦截调用,解析方法 B 上@Transactional注解的属性(如传播行为、隔离级别),生成TransactionDefinition对象。

步骤 2:判断当前线程是否已有事务

事务管理器通过TransactionSynchronizationManagerhasResource(...)方法,检查当前线程的ThreadLocal中是否绑定了事务资源(如数据库连接)。

  • 如果有资源,说明当前线程已有事务(可能是方法 A 创建的);
  • 如果没有,说明当前线程无事务。
步骤 3:根据传播行为决策事务操作

事务管理器的getTransaction()方法根据 “当前是否有事务” 和 “传播行为”,执行不同逻辑:

传播行为决策逻辑(核心)
REQUIRED若当前有事务,复用当前事务(返回已有的 TransactionStatus);若没有,新建事务。
REQUIRES_NEW无论当前是否有事务,都新建一个事务;若有当前事务,先挂起(存入 ThreadLocal)。
SUPPORTS若当前有事务,复用;若没有,以非事务方式执行(不创建事务)。
MANDATORY若当前有事务,复用;若没有,直接抛出异常(要求必须在事务中执行)。
步骤 4:维护事务状态(TransactionStatus)
  • 对于新建的事务TransactionStatus会标记isNewTransaction()=true,并将事务资源(如数据库连接)通过TransactionSynchronizationManager绑定到当前线程。
  • 对于复用的事务TransactionStatus会关联到外层事务的状态,同时记录 “嵌套层级”(方便后续提交 / 回滚时判断是否是最外层事务)。
  • 对于挂起的事务(如 REQUIRES_NEW):会将当前事务的状态存入ThreadLocal的 “挂起队列”,待新事务完成后恢复。
步骤 5:事务执行与后续处理

方法 B 执行完成后,TransactionInterceptor会根据执行结果(正常 / 异常)和TransactionStatus决定提交或回滚:

  • 若方法 B 是新建事务(如 REQUIRES_NEW 或 REQUIRED 且无外层事务):直接提交或回滚,并解绑线程资源;
  • 若方法 B 是复用外层事务(如 REQUIRED 且有外层事务):仅标记事务状态(如异常时标记rollbackOnly),最终由最外层事务统一提交 / 回滚;
  • 若方法 B挂起了外层事务(如 REQUIRES_NEW):提交 / 回滚新事务后,从ThreadLocal中恢复被挂起的外层事务,继续执行外层逻辑。

四、关键细节:嵌套事务的状态管理

传播机制的核心难点是 “嵌套事务的状态同步”,例如:

  • 当内层方法(REQUIRED)抛出异常时,会将外层事务的TransactionStatus标记为rollbackOnly,外层方法执行到最后会发现这个标记,从而触发整体回滚;
  • 当内层方法使用 REQUIRES_NEW 时,它的事务独立于外层,内层提交 / 回滚不会影响外层(但外层可以捕获内层异常后继续执行)。

这一切都依赖TransactionStatus对状态的精准记录,以及TransactionSynchronizationManager对线程上下文的维护 —— 确保事务状态在嵌套调用中不混乱。

总结

声明式事务传播机制的实现,本质是:


通过 AOP 拦截事务方法,解析传播规则,结合线程本地存储(ThreadLocal)感知当前事务状态,由事务管理器动态决策事务的创建、复用或挂起,并通过事务状态(TransactionStatus)维护嵌套关系,最终实现多个事务方法嵌套时的自动化事务管理

理解传播机制的关键,在于把握 “当前线程事务状态” 与 “传播行为规则” 的对应关系,以及TransactionStatus如何串联起整个事务的生命周期。

如果这篇文章对大家有帮助可以点赞关注,你的支持就是我的动力😊!

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

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

相关文章

@Transactional事务注解的批量回滚机制

关键机制说明:1.​​事务注解生效​​:Transactional(rollbackFor Exception.class)Override Transactional(rollbackFor Exception.class) public Boolean saveUser(UserDTO userDto) {SysUser sysUser new SysUser();BeanUtils.copyProperties(user…

飞算 JavaAI 深度体验:开启 Java 开发智能化新纪元

个人主页:♡喜欢做梦 欢迎 👍点赞 ➕关注 ❤️收藏 💬评论 目录 一、引言 二、飞算 JavaAI 初印象与功能概览 (一)初识飞算 JavaAI (二)核心功能模块概览 三、智能代码生成功能深度体…

pandas销售数据分析

pandas销售数据分析 数据保存在data目录 消费者数据:customers.csv商品数据:products.csv交易数据:transactions.csv customers.csv数据结构:字段描述customer_id客户IDgender性别age年龄region地区membership_date会员日期produc…

访问Windows服务器备份SQL SERVER数据库

以前没有直接访问过Windows服务器,今天刚一看到的是时候有点懵,竟然下意识的使用SecureCRT远程工具去连了一下,然后领导说,看一下用户名,突然意识到,跟我们平时远程桌面是一样的。 一、 win + R 打开命令窗口 二、 输入 mstsc 三、 输入远程地址 四、点击连接,如果有弹…

C++ 面向对象 - 对象定义方法汇总

C对象定义方法汇总 1. 栈上定义方式 1.1 调用无参构造函数的定义方式 无参构造函数有两种: 默认无参构造函数Demo(){}默认值列表构造函数。Demo():a{1},b{2}{} // 使用初始化列表实现对象定义方式: Demo d; Demo d1{}; // 以下定义方式还调用了拷贝构造…

指尖上的魔法:优雅高效的Linux命令手册

一、Linux基础指令 1. ls ls:对于目录,列出该目录下的所有子目录与文件,对于文件,将列出文件名以及其他信息。 -a:列出目录下的所有文件,包含以.开头的隐藏文件 -l:列出文件的详细信息 -d:将目录…

《磁力下载工具实测:资源搜索+高速下载一站式解决方案》

嘿,朋友们!我是阿灿,今天给大家带来一个超实用的看片神器,特别适合老司机们使用,保证让你眼前一亮!推荐一款比某雷更好用的下载工具,搭配资源搜索神器,轻松获取资源不限速。超强磁力…

Go网络编程基础:网络模型与协议栈概述 - 从理论到实践的完整指南

1. 引言 在当今的互联网时代,网络编程已经成为后端开发的核心技能。Go语言以其出色的并发性能和简洁的语法,在网络编程领域展现出了强大的优势。从Docker、Kubernetes到众多微服务框架,Go已经成为构建高性能网络应用的首选语言之一。 你是否…

Web攻防-SSTI服务端模版注入利用分类语言引擎数据渲染项目工具挖掘思路

知识点: 1、WEB攻防-SSTI-利用分类&功能点 2、WEB攻防-SSTI-利用项目&挖掘思路 SSTI(Server Side Template Injection) 服务器模板注入, 服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中&…

李沐动手学深度学习Pytorch-v2笔记【07自动求导代码实现】

文章目录前言自动求导实现非标量变量的反向传播分离计算Python控制流的梯度计算前言 关于走动求导的理论知识个人有点难以理解,推荐大家去看https://blog.csdn.net/weixin_42831564/article/details/135658138这篇文章,讲的很好。 自动求导实现 impor…

strchr 与 strstr 函数详解

一.strchr - 字符查找函数1.函数原型char *strchr(const char *str, int c);2.核心功能在字符串中查找特定字符的第一次出现位置3.参数说明参数 类型 说明str const char* 要搜索的字符串c int 要查找的字符(自动转换为char)4.返回值…

jakes信道模型

Jakes 模型 前面我们介绍了多径信道合成信号可表示为: r(t)Re{∑i0N(t)−1ai(t)u(t−τi(t))ej2πfc(t−τi(t))ϕDi(t)} r(t)Re \left\{\sum_{i0}^{N(t)-1}a_{i}(t)u(t-\tau_{i}(t))e^{j2\pi f_{c}(t-\tau_{i}(t))\phi_{D_{i}}(t)} \right\} r(t)…

JVM类加载机制解析

什么是类加载器? 类加载器是JVM的核心组件之一,负责将Java字节码文件(.class文件)加载到JVM内存中。由于JVM只能执行二进制字节码,类加载器的作用就是将编译后的.class文件转换为JVM可以理解和执行的格式,使…

用Python和OpenCV从零搭建一个完整的双目视觉系统(二)

本系列文章旨在系统性地阐述如何利用 Python 与 OpenCV 库,从零开始构建一个完整的双目立体视觉系统。 本项目github地址:https://github.com/present-cjn/stereo-vision-python.git 项目架构设计:蓝图、分工与工作流 在上一篇文章中&#…

亿级流量下的缓存架构设计:Redis+Caffeine多级缓存实战

亿级流量下的缓存架构设计:RedisCaffeine多级缓存实战 一、为什么需要多级缓存? 在亿级流量场景下,单纯依赖Redis会遇到三大瓶颈:网络延迟:Redis远程访问通常需要1-5ms,QPS超过10万时成为瓶颈资源成本&…

AI基建还能投多久?高盛:2-3年不是问题,回报窗口才刚开启

高盛表示,尽管AI商业化变现仍处早期阶段,但基于成本削减的第一阶段回报已经显现。预测到2030年AI自动化可为财富500强企业节省约9350亿美元成本。分析师认为,这一早期收益足以支撑当前AI基础设施投资水平,尽管增长率可能放缓。虽然…

【mac】快捷键使用指南

在Mac上,根据选择对象的不同,在选择时移动的方法也有所不同,以下是具体介绍: 移动文件或文件夹:可通过拖放操作移动。打开“访达”(Finder),找到要移动的文件或文件夹,按…

CS144 lab2 tcp_receiver

1. 实验目的 lab2 的目的是实现tcp的接收端。 主要包括两方面 (1) 从发送端接收消息,使用Reassembler聚合字节流(Bytestream) (2)将确认号(ackno)和window size发回对端 …

【论文笔记】A Deep Reinforcement Learning Based Real-Time Solution Policy for the TSP

《基于 DRL 和 DCNN 的实时 TSP 求解策略》IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS, VOL. 24, NO. 6, JUNE 2023一段话总结本文提出了一种基于深度强化学习(DRL) 和深度卷积神经网络(DCNN) 的实时旅行商问题&am…

MMaDA:多模态大型扩散语言模型

集众家之所长,成大一统。普林斯顿大学、北京大学、清华大学、字节跳动的研究者将“文本推理、多模态分析、图像生成”三大方向融合在一个单一扩散模型里,并用恰当的优化策略来提升模型在各个方向的性能。 研究动机 研究人员致力于开发一个能够处理多种模…