前言

相信小伙伴一定用过 @Transaction 注解,那 @Transaction 背后的秘密又知道多少呢?

Spring 是如何开启事务的?又是如何进行提交事务和关闭事务的呢?

画图猜测

在开始 debug 阅读源码之前,小伙伴们应该已经知道 MySQL 是如何开启事务的。

因此可以得出猜测:

那下面跟着源码一起读一读,Spring 的 @Transaction 注解是如何执行事务逻辑的?

Spring 事务执行流程

开启事务

这里使用的是 Spring Boot + MySQL + Druid

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>

  1. 在创建 Bean 的时候,会对 UserService 基于 AOP 生成代理对象;

AbstractAutowireCapableBeanFactory#initializeBean

...

wrapIfNecessary

AbstractAutoProxyCreator#createProxy

CglibAopProxy#getProxy 生成代理对象

  • 开始执行 userService.updateUserInfo(); 这里的 userService 就是代理对象;会被 CglibAopProxy.DynamicAdvisedInterceptor#intercept 方法拦截;

  • TransactionInterceptor#invoke 被事务拦截器拦截

  • TransactionAspectSupport#invokeWithinTransaction 事务处理

  • AbstractPlatformTransactionManager#getTransaction 会在这里调用 AbstractPlatformTransactionManager#startTransaction 方法,来开启事务。

是不是看到 doBegin 这个词突然感觉很熟悉。

跟进 DataSourceTransactionManager#doBegin 方法,注意看,此时是在 spring-jdbc-5.3.8.jar 包下面的。

因为使用的 druid 连接池,所以这块 Connection 是 durid 的连接池。

  • DruidPooledConnection#setAutoCommit(false) 关闭自动提交;

这里就是 druid 的逻辑,一顿执行然后到 com.alibaba.druid.filter.FilterChainImpl#connection_setAutoCommit。

  • ConnectionImpl#setAutoCommit,这个是在 mysql-connector-java-8.0.25.jar 包下的。

这一句才是重点 SET autocommit=0。

SET autocommit=0

开启事务了!

总结一下流程:

执行 SQL

在开始事务之后,会通过回调执行方法的内部逻辑。

  • 因为这里使用的是 Mybatis,所以还是会被代理,MapperProxy#invoke;

  • DruidPooledPreparedStatement#execute;

  • ClientPreparedStatement#execute;

执行过程相对比较简单:

提交事务

在 TransactionAspectSupport#invokeWithinTransaction 最后一行,commitTransactionAfterReturning(txInfo); 就是提交事务。

  • AbstractPlatformTransactionManager#commit 抽象事务管理器,进行提交事务

  • DataSourceTransactionManager#doCommit 数据源数据管理器,提交事务

这里肯定是调用连接池的方法,所以会执行到 DruidPooledConnection 中

  • DruidPooledConnection commit

  • 最终还是执行到 mysql-connector-java-8.0.25.jar 包下面的 ConnectionImpl#commit

调用 commit 提交事务。

commit

异常回滚

异常在这里 TransactionAspectSupport#invokeWithinTransaction 会被 catch。

AbstractPlatformTransactionManager#rollback 在这里进行 rollback

执行 DataSourceTransactionManager#doRollback

最终执行到 mysql-connector-java-8.0.25.jar 的 ConnectionImpl#rollback() 到 ConnectionImpl#rollbackNoChecks

从而执行 rollback 语句

rollback

恢复 autocommit

cleanupTransactionInfo(txInfo);

在 这个方法中会将之前设置的 autocommit 进行恢复。

Java 原生开启事务

如果觉得这样有点绕,那咱们可以看简单版本的,不带 Spring。

/**
* @author liuzhihang
* @date 2021/6/18 16:51
*/
public class MainTest { public static void main(String[] args) throws Exception { DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/demo");
dataSource.setUsername("root");
dataSource.setPassword("root"); Connection connection = dataSource.getConnection(); try {
// 关闭自动提交
connection.setAutoCommit(false); connection.prepareStatement("update user_info set user_name = 'liuzhihang' where user_id = '1001';").executeUpdate();
connection.prepareStatement("update user_address set address = 'anhui' where user_id = '1001';").executeUpdate();
// 提交事务
connection.commit();
} catch (Exception e) {
// 回滚
connection.rollback();
} finally {
// 开启自动提交
connection.setAutoCommit(true);
}
}
}

看完 Java 原生提交事务的方式,是不是感觉简单明了。

Spring @Transaction 只是创建了 AOP 代理,通过代理调用原生的开启关闭事务,同样在执行 SQL 那一块,也是 Mybatis 进行了代理,从而提交 SQL。

总结

最后,将图进行合并,总结流程。

至此,事务执行过程分析完毕。

不过还是有一个疑问?

为什么使用 set autocommit = 0 来开启事务,而不是使用 begin 或者 start transaction 来开启事务呢?

相关推荐

Spring @Transaction 注解是如何执行事务的?的更多相关文章

  1. Spring使用注解方式就行事务管理

    使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间<beans xmlns="http://www.springframework.org/schema/b ...

  2. spring基于注解的声明式事务控制

    package com.hope.service.impl;import com.hope.dao.IAccountDao;import com.hope.domain.Account;import ...

  3. 阶段3 2.Spring_10.Spring中事务控制_7 spring基于注解的声明式事务控制

    创建新项目 复制上一个pom.xml的内容.依赖和打包的方式 再复制src的代码过来 bean.xml.多导入context的声明 Service的实现类增加注解 dao的set方法删掉 通过Auto ...

  4. Spring整合JMS(四)——事务管理

    原文链接:http://haohaoxuexi.iteye.com/blog/1983532 Spring提供了一个JmsTransactionManager用于对JMS ConnectionFact ...

  5. Spring整合JMS(四)——事务管理(转)

    *注:别人那复制来的 Spring提供了一个JmsTransactionManager用于对JMS ConnectionFactory做事务管理.这将允许JMS应用利用Spring的事务管理特性.Jm ...

  6. spring事物配置,声明式事务管理和基于@Transactional注解的使用

    http://blog.csdn.net/bao19901210/article/details/41724355 http://www.cnblogs.com/leiOOlei/p/3725911. ...

  7. spring注解实现业务层事务管理,当业务层自调用时,事务失效问题解决

    前些日子一朋友在需要在目标对象中进行自我调用,且需要实施相应的事务定义,且网上的一种通过BeanPostProcessor的解决方案是存在问题的.因此专门写此篇帖子分析why. 1.预备知识 aop概 ...

  8. Spring 使用注解对事务控制详解与实例

    1.什么是事务 一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败. 事务的四个特征ACID: 原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分 ...

  9. Spring系列之事务的控制 注解实现+xml实现+事务的隔离等级

    Spring系列之事务的控制 注解实现+xml实现 在前面我写过一篇关于事务的文章,大家可以先去看看那一篇再看这一篇,学习起来会更加得心应手 链接:https://blog.csdn.net/pjh8 ...

随机推荐

  1. Pytorch_Part2_数据模块

    VisualPytorch beta发布了! 功能概述:通过可视化拖拽网络层方式搭建模型,可选择不同数据集.损失函数.优化器生成可运行pytorch代码 扩展功能:1. 模型搭建支持模块的嵌套:2. ...

  2. 服务治理演进剖析 & Service Mesh、 xDS核心原理梳理

    基于XDS协议实现控制面板与数据面板通信分享 基于这段时间在同程艺龙基础架构部的蹲坑,聊一聊微服务治理的核心难点.历史演进.最新动态, 以上内容属自我思考,不代表同程艺龙技术水准.如理解有偏差.理解不 ...

  3. CRM系统实施的原则

    在我们使用CRM系统服务企业和客户之前,需要先系统的实施它.使用CRM系统却没有发挥它应有价值的案例很多,那么我们要怎样才能让CRM的作用发挥到最大,并确保它是成功的?那么今天小编跟您聊一聊,您的企业 ...

  4. Duplicate entry '' for key 'PRIMARY'

    今天在在mysql中插入数据 因为直接插入查询出来的表格,insert into 表(student_id,class_id) 直接插入了这两个字段对应的查询出来的表 没有留意到该表的主键没有设置自增 ...

  5. 虚拟机快速下载安装配置aarch64-linux-gnu-gcc工具链

    方式一:软件仓库安装 此方法不用自己去配置交叉编译工具链 1.查看本地仓库有支持哪些版本哪些 输入命令: apt-cache search aarch64 2.下载安装 gcc-8-aarch64-l ...

  6. JSX语法详解

    一.基础1.JSX是什么JSX是一种像下面这样的语法: const element = <h1>Hello, world!</h1>;1它是一种JavaScript语法扩展,在 ...

  7. 持续集成和持续交付工具-jenkins

    jenkins说明 jenkins是一款由Java编写的开源的持续集成工具,它运行在Servlet容器中(例如Apache Tomcat).它支持软件配置管理(SCM)工具(包括AccuRev SCM ...

  8. CentOS8.2集成的megaraid_sas版本不支持IBM X3850 X5内置RAID卡。需要更新https://docs.broadcom.com/docs/MR_LINUX_DRIVER_7.15-07.715.02.00-1-PUL.tgz

    CentOS8.2集成的megaraid_sas版本不支持IBM X3850 X5内置RAID卡.需要更新https://docs.broadcom.com/docs/MR_LINUX_DRIVER_ ...

  9. Windows 电脑的四种运行状态工作状态 (Working), S0 睡眠状态 (Sleep), S1 或 S3 休眠状态 (Hibernate), S4 关机状态 (Shutdown), S5

    == Windows 电脑的四种运行状态 == 这四种运行状态(或称电源状态)是: 工作状态 (Working), S0 睡眠状态 (Sleep), S1 或 S3 休眠状态 (Hibernate), ...

  10. 寻找CPU使用率高的进程方法

    寻找CPU使用率高的进程方法 发布时间:  2017-07-13 浏览次数:  1362 下载次数:  0 问题描述 节点报CPU使用率高,甚至出现"ALM-12016 CPU使用率超过阈值 ...