Spring事务原理 一

Spring事务管理有 声明式事务 和 编程式事务 两种方式,实现对数据库操作的ACID控制。其核心思想是将事务管理与业务逻辑解耦,开发者通过简单注解或配置即可管理复杂事务。

开启Spring事务,本质上就是在Spring容器中增加了一个Advisor,拦截带有@Transaction的方法,在初始化后阶段创建代理对象。当代理对象执行方法前,设置数据库连接的autocommit改为false,在方法正常返回时执行commit,在异常时执行rollback。

本文中源码来自Spring 5.3.x分支,github源码地址:GitHub - spring-projects/spring-framework: Spring Framework

一 创建代理对象

当在配置类上使用@EnableTransactionManagement注解时,通过@Import导入了TransactionManagementConfigurationSelector类

该注解有两个属性

  1. proxyTargetClass:使用基于类的Cglib代理技术,默认为false。即使用JDK动态代理;
  2. AdviceMode:代理模式,枚举值有PROXY、ASPECTJ,默认为基于通知的JDK代理。
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;

TransactionManagementConfigurationSelector是ImportSelector接口实现,在selectImports方法中,引入了两个bean:

  1. AutoProxyRegistrar:在初始化后阶段创建代理对象;
  2. ProxyTransactionManagementConfiguration:定义Pointcut、Advice,创建Advisor。

有了这两个bean,Spring就能自行判断哪些bean需要被代理,代理逻辑是什么,从而创建代理对象。

1.1 AutoProxyRegistrar类

AutoProxyRegistrar类是ImportBeanDefinitionRegistrar接口的实现,在registerBeanDefinitions方法中,向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的beanDefinition。

而InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator,本质上是一个BeanPostProcessor。

其作用就是开启自动代理,在初始化后阶段去寻找容器中Advisor类型的Bean,判断并为某个Bean创建代理对象。

1.2 ProxyTransactionManagementConfiguration类

该类是一个配置类,它又定义了三个bean,创建了Advisor对象:

  1. AnnotationTransactionAttributeSource:相当于Pointcut,判断某个类或方法上是否存在@Transactional注解;
  2. TransactionInterceptor:一个Advice,定义了代理逻辑;
  3. BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor,由AnnotationTransactionAttributeSource、TransactionInterceptor的对象组成。

二 执行事务的大体流程

2.1 相关接口

  • PlatformTransactionManager:事务管理器的顶层接口,定义了事务的提交(commit)、回滚(rollback)和获取当前事务状态(getTransaction)的方法。
  • TransactionDefinition:定义事务的属性(传播行为、隔离级别、超时时间、是否只读等)。
  • TransactionStatus:描述事务的运行时状态(是否完成、是否回滚等)。

PlatformTransactionManager常见实现类有:

    • JDBC:DataSourceTransactionManager(适用于原生JDBC或MyBatis)
    • JPA:JpaTransactionManager
    • Hibernate:HibernateTransactionManager
    • JTA:JtaTransactionManager(分布式事务)

2.2 执行流程

当代理对象在执行某个方法时,会再次判断方法是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行
TransactionInterceptor.invoke()方法,基本流程为:

  1. 利用所配置的PlatformTransactionManager获取一个数据库连接(其中会处理事务传播行为);
  2. 修改数据库连接的autocommit为false;
  3. 执行MethodInvocation.proceed()方法,即执行业务方法;
  4. 如果方法没有抛异常,则提交事务;
  5. 如果方法抛了异常,则回滚事务。
// 伪代码:TransactionInterceptor的核心逻辑
public Object invoke(MethodInvocation invocation) {// 1. 获取事务属性(@Transactional配置)TransactionAttribute txAttr = getTransactionAttribute(method);// 2. 获取事务管理器(PlatformTransactionManager)PlatformTransactionManager tm = determineTransactionManager(txAttr);// 3. 根据传播行为决定是否创建新事务TransactionStatus status = tm.getTransaction(txAttr);try {// 4. 执行业务方法Object result = invocation.proceed();// 5. 提交事务tm.commit(status);return result;} catch (Exception ex) {// 6. 根据异常类型回滚事务completeTransactionAfterThrowing(txAttr, status, ex);throw ex;}
}

三 声明式事务和编程式事务

3.1 声明式事务

即通过@Transactional让业务方法按指定的事务类型执行。

  • 创建DataSource、DataSourceTransactionManager
@Configuration
@EnableTransactionManagement
public class AppConfig {@Beanpublic DataSource dataSource() {// 配置数据源(如HikariCP)return new HikariDataSource();}@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}
}
  • 使用@Transactional
@Service
public class OrderService {@Autowiredprivate OrderDao orderDao;// 指定传播行为和隔离级别@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)public void createOrder(Order order) {orderDao.save(order);// 其他数据库操作(如更新库存)updateInventory(order.getItems());}@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateInventory(List<Item> items) {// 更新库存逻辑}
}

3.2 编程式事务管理

  • 使用TransactionTemplate
@Service
public class PaymentService {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate PaymentDao paymentDao;public void processPayment(Payment payment) {transactionTemplate.execute(status -> {try {// 执行数据库操作paymentDao.save(payment);return true;} catch (Exception e) {// 标记回滚status.setRollbackOnly();return false;}});}
}
  • 直接使用PlatformTransactionManager
public void manualTransaction() {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 业务操作transactionManager.commit(status);} catch (Exception ex) {transactionManager.rollback(status);throw ex;}
}

下一篇文章中将详细介绍事务的传播机制。

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

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

相关文章

一周学会Flask3 Python Web开发-Debug模式开启

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 默认情况&#xff0c;项目开发是普通模式&#xff0c;也就是你修改了代码&#xff0c;必须重启项目&#xff0c;新代码才生效&…

使用EasyExcel和多线程实现高效数据导出

​ 使用EasyExcel和多线程实现高效数据导出 1. 概述 在企业级应用中&#xff0c;数据导出是一个常见的需求。为了提高导出效率&#xff0c;尤其是在处理大量数据时&#xff0c;我们可以结合使用EasyExcel库和多线程技术。本文将详细介绍如何通过EasyExcel和多线程技术实现高…

[qt5学习笔记]Application Example示例程序源码解析

开发环境问题 vs2022下直接打开ui、ts文件失败 解决办法如下图&#xff0c; 设置designer独立运行。估计是嵌入运行存在些许bug。 同理&#xff0c;ts编辑工具linguist也存在这个问题。 qrc rc的编辑嵌入编辑都正常&#xff0c;但分离式更稳定可靠。 qt creator编译失败 原…

Jetson Agx Orin平台JP6.0-r36.3版本修复了vi模式下的原始图像损坏(线条伪影)

1.问题描述 这是JP-6.0 GA/ l4t-r36.3.0的一个已知问题 通过vi模式捕获的图像会导致异常线条 参考下面的快照来演示这些线伪影 这个问题只能通过VI模式进行修复,不应该通过LibArgus看到。 此外,这是由于内存问题。 由于upstream已经将属性名称更改为“dma-noncoherent”…

[创业之路-299]:图解金融体系结构

一、金融体系结构 1.1 概述 金融体系结构是一个国家以行政的、法律的形式和运用经济规律确定的金融系统结构&#xff0c;以及构成这个系统的各种类型的银行和非银行金融机构的职能作用和相互关系。以下是对金融体系结构的详细分析&#xff1a; 1、金融体系的构成要素 现代金…

0基础学LabVIEW

对于零基础的朋友来说&#xff0c;学习LabVIEW需要一个科学的学习路径和方法。通过观看优质的B站教程打好基础&#xff0c;再结合实际项目进行实践操作&#xff0c;能够快速提升LabVIEW的应用能力。以下是从入门到进阶的学习建议。 ​ 一、利用B站入门教程打基础 筛选优质教程…

Query String 传递 json 对象参数、map参数

?params[name]John&params[age]30&params[isStudent]true params[name] 和 params[age] 中的 [] 是非法字符。 服务器&#xff08;Apache Tomcat&#xff09;默认不允许在 URL 中使用 []。 对 [] 进行 URL 编码 将 [] 编码为 %5B 和 %5D。 示例&#xff1a; ?pa…

腿足机器人之六- 前向运动学

腿足机器人之六- 前向运动学 刚体运动学基础坐标系定义旋转矩阵与欧拉角齐次变换矩阵&#xff08;平移旋转的统一表示&#xff09; 运动链建模串联运动链结构&#xff08;从基座到末端的关节连接&#xff09;标准Denavit-Hartenberg&#xff08;D-H&#xff09;参数法改进D-H参…

正则表达式(Regular expresssion)

正则表达式 匹配单次 . &#xff1a;匹配任意一个字符 [ ] &#xff1a;匹配[ ]里举例的任意一个字符 /d &#xff1a;匹配数字0-9 /D &#xff1a;匹配非数字 /s &#xff1a;匹配空白或tab建 /S &#xff1a;匹配非空白 /w &#xff1a;…

DarkLabel 2.4使用指南:高效标注视频数据目标检测标签

工具概述 DarkLabel 2.4 是一款强大的多功能标注工具&#xff0c;专为计算机视觉开发者设计&#xff0c;旨在提升标注工作的效率和精确度。其智能标注引擎支持两项核心功能&#xff1a;线性插值标注与多目标跟踪&#xff0c;极大地优化了视频标注过程。 &#xff08;1&#x…

rabbitmq五种模式的总结——附java-se实现(详细)

rabbitmq五种模式的总结 完整项目地址&#xff1a;https://github.com/9lucifer/rabbitmq4j-learning 一、简单模式 &#xff08;一&#xff09;简单模式概述 RabbitMQ 的简单模式是最基础的消息队列模式&#xff0c;包含以下两个角色&#xff1a; 生产者&#xff1a;负责发…

网页制作01-html,css,javascript初认识のhtml的基本标记

一、 Html简介 英文全称是 hyper text markup language,超文本标记语言,是全球广域网上描述网页内容和外观的标准. Html作为一款标记语言,本身不能显示在浏览器中.标记语言经过浏览器的解释和编译,才能正确地反映html标记语言的内容. 1.html 的基本标记 1&#xff09;头部标…

Blackbox.AI:高效智能的生产力工具新选择

前言 在当今数字化时代&#xff0c;一款高效、智能且功能全面的工具对于开发者、设计师以及全栈工程师来说至关重要。Blackbox.AI凭借其独特的产品特点&#xff0c;在众多生产力工具中脱颖而出&#xff0c;成为了我近期测评的焦点。以下是我对Blackbox.AI的详细测评&#xff0…

海康摄像头IPV6模式,手动,自动,路由公告

海康摄像头DS-2DC7220IW-A 网络设置中的IPv6配置选项。IPv6是互联网协议&#xff08;IP&#xff09;的第六版&#xff0c;用于替代IPv4&#xff0c;提供更多的IP地址和改进的网络功能。图片中的选项允许用户选择如何配置设备的IPv6网络连接&#xff1a; 手动&#xff1a;用户可…

【kafka系列】Kafka如何实现高吞吐量?

目录 1. 生产者端优化 核心机制&#xff1a; 关键参数&#xff1a; 2. Broker端优化 核心机制&#xff1a; 关键源码逻辑&#xff1a; 3. 消费者端优化 核心机制&#xff1a; 关键参数&#xff1a; 全链路优化流程 吞吐量瓶颈与调优 总结 Kafka的高吞吐能力源于其生…

sql sqlserver的特殊函数COALESCE和PIVOT的用法分析

一、COALESCE是一个返回参数中第一个非NULL值的函数&#xff0c; 列如&#xff1a;COALESCE&#xff08;a,b,c,d,e&#xff09;;可以按照顺序取abcde&#xff0c;中的第一个非空数据&#xff0c;abcde可以是表达式 用case when 加ISNULL也可以实现&#xff0c;但是写法复杂了…

unity学习44:学习Animator 的一个动作捕捉网站,实测好用

目录 1 动作捕捉网站 2 注册和下载 3 比如首页的内容&#xff0c;可以直接下载为fbx模型文件 4 上传并修改 5 在 unity里使用 5.1 下载的fbx文件直接拖入到unity 5.2 动画修改 5.3 游戏里播放 1 动作捕捉网站 一个动作捕捉网站 AI神器集合网站 千面视频动捕 | AI神器…

CPP集群聊天服务器开发实践(六):Redis发布订阅消息队列及服务器集群通信

前文实现了单服务器与多客户端之间的通信以及聊天业务&#xff0c;同时为了增大并发量利用nginx实现多服务器的集群负载均衡&#xff0c;但是一个关键的问题是要实现多服务器之间的通信&#xff0c;这里采用Redis的发布订阅消息队列实现。 不同客户端可能连接在不同服务器上&am…

掌握SQLite_轻量级数据库的全面指南

1. 引言 1.1 SQLite简介 SQLite 是一个嵌入式关系型数据库管理系统,它不需要单独的服务器进程或系统配置。它的设计目标是简单、高效、可靠,适用于各种应用场景,尤其是移动设备和嵌入式系统。 1.2 为什么选择SQLite 轻量级:文件大小通常在几百KB到几MB之间。无服务器架构…

基于javaweb的SpringBootoa办公自动化系统设计和实现(源码+文档+部署讲解)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 运行环境开发工具适用功能说明部分代码展示 运行环境 Java≥8、MySQL≥5.7 开发工具 eclipse/idea/myeclipse/sts等均可配置运行…