读书笔记-《Spring技术内幕》(四)事务

前面我们依次学习了 IoC、AOP、MVC(读书笔记-《Spring技术内幕》(一)IoC容器的实现读书笔记-《Spring技术内幕》(二)AOP的实现读书笔记-《Spring技术内幕》(三)MVC与Web环境),已经涵盖了 Spring 最核心的内容。

今天,我们再来研究一个比较常用的组件------事务,然后这本书的读书笔记就可以完结了~


01

Spring 事务概述

按照惯例,我们先从程序员的视角出发,看看 Spring 帮我们做了什么,再学习其具体的设计与实现。

在没有使用 Spring 的 JavaWeb 项目中,是怎么实现事务的呢?请看下面的示例代码:

java 复制代码
public void hello {
    Connection conn = openConnection();
    try {
        conn.setAutoCommit(false);
        // 业务代码
        conn.commit();
    } catch (SQLException e) {
        conn.rollback();
    } finally {
        conn.setAutoCommit(true);
        conn.close();
    }
}

这个 Connection 我印象很深,初学时因为它学习到了第一个设计模式------单例模式,这个模式的懒汉/饿汉实现、双重检测是早期常见的面试题。(跑题了,赶紧拉回来......)

简单来说,这里的代码直接操作数据库连接,并且将事务处理代码和业务代码耦合,非常糟糕。

而在 Spring 的帮助下,我们只需要一行注解,就很优雅。

java 复制代码
@Transactional
public void world {
    // 业务代码
}

看到这种将非业务功能代码解耦出来,并通过注解(声明式)实现功能的操作,很容易猜到,其原理是通过 AOP 将事务处理的功能编织进来,本质上可以看作是一个基于 Spring IoC、AOP 的优秀应用。 (注意:后面默认指代的是声明式使用,Spring 事务也可以编程式使用,其实现非常简单,不涉及框架特性,但是会耦合业务代码,本文不做讲述)

既然如此,从流程上看 Spring 事务的实现就有两个重点

  • 如何读取配置,并构造这个代理对象?

  • 这个代理对象如何实现事务的创建、提交、回滚等等?


02

Spring 事务设计概览

在回答上面两个问题之前,我们先看看类层次结构。

简单概括并补充一下:

  • ProxyConfig、FactoryBean 等:为前面 IoC、AOP 模块的设计,不做赘述。

  • **TransactionProxyFactoryBean:**生成代理对象。

  • **TransactionInterceptor:核心类,**对代理方法进行拦截,将事务功能编织进来。

  • **PlatformTransactionManager、AbstractPlatformTransactionManager:**封装底层不同数据库对事务的实现,如生成、提交、回滚、挂起等。

  • **TransactionAttribute:**事务配置信息在 Spring 中的抽象。

  • **TransactionInfo:**事务信息抽象,包含事务和 TransactionStatus。


    03

    构建代理对象

​​​​​​​​​​​​​​

​​​​​​​****

构建代理对象的时序图如上所示,用文字概括一下:

  • 在 IoC 容器完成 Bean 的依赖注入时,通过 initializeBean() 调用 createMainInterceptor(),创建一个 TransactionAttributePointcut,为读取 TransactionAttribute 做准备。

  • 由于 AbstractSingletonProxyFactoryBean 实现了 InitializingBean 接口,在 afterPropertiesSet() 中会实例化 ProxyFactory,设置通知、目标对象,最终返回代理对象。

  • 在构建好代理对象后,调用代理方法时便会调用相应的 TransactionInterceptor,匹配对应的配置。(举个例子的话可以看看 NameMatchTransactionAttributeSource,其通过成员变量 nameMap 的维护来实现名称匹配)


04

****处理事务

构建好代理对象后,对原方法的调用就会被拦截,也就是进入 TransactionInterceptor 的 invoke()。其会依次获取事务处理配置、PlatformTransactionManager,并交由这个具体的处理器来实现事务的创建、提交、回滚等等。

这里我们就以事务的创建为例,看看 TransactionAspectSupport 的 createTransactionIfNecessary 方法的时序图。

这里就两点可以留意下:

  • 针对不同的事务传播机制,源码里有各种条件分支。(不过在实际工作中,我还没使用过非默认的传播机制,一般是通过 MQ 来保障最终一致性)

  • bindToThread() 是通过 TransactionAspectSupport 的成员变量 ThreadLocal<TransactionInfo> transactionInfoHolder 实现,其也体现了事务的隔离性。

至此,我们只需再进一步就可抵达终点了。

前面的类层次结构图有提到 AbstractPlatformTransactionManager,其定义了事务的生成、提交、回滚、挂起,对于不同的数据库有不同的实现。

以 DataSourceTransactionManager 为例,点开它的源码一看,我们就会发现非常眼熟。它就和一开始我们写的示例代码类似,直接操作 Connection,打印日志等等。


​​​​​​​

原文链接读书笔记-《Spring技术内幕》(四)事务

原创不易,点个关注不迷路哟,谢谢~

文章推荐:

相关推荐
DuelCode22 分钟前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
优创学社226 分钟前
基于springboot的社区生鲜团购系统
java·spring boot·后端
好好研究26 分钟前
学习栈和队列的插入和删除操作
数据结构·学习
why技术29 分钟前
Stack Overflow,轰然倒下!
前端·人工智能·后端
幽络源小助理33 分钟前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
猴哥源码34 分钟前
基于Java+springboot 的车险理赔信息管理系统
java·spring boot
YuTaoShao1 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
新中地GIS开发老师1 小时前
新发布:26考研院校和专业大纲
学习·考研·arcgis·大学生·遥感·gis开发·地理信息科学
ai小鬼头2 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
Dcs2 小时前
超强推理不止“大”——手把手教你部署 Mistral Small 3.2 24B 大模型
java