【Spring】事务实现原理
在使用事务的时候需要添加@EnableTransactionManagement注解来开启事务,Spring事务底层是通过AOP来实现的,所以启用事务后,同样会向容器中注入一个代理对象创建器,AOP使用的是AnnotationAwareAspectJAutoProxyCreator,事务使用的是InfrastructureAdvisorAutoProxyCreator。
Advice通知:定义在切点上需要执行什么样的操作;
PointCut切点:定义在哪些方法上使用通知;
Advisor:Advice和Pointcut加起来组成了Advisor,可以看做是对切面的封装;
在使用AOP时,一般会创建一个切面,里面包含了切点和通知,事务既然基于AOP实现,所以也会有对应的通知和切点。
事务Advisor
开启事务时,还会向Spring容器中注册一个BeanFactoryTransactionAttributeSourceAdvisor,从名字上可以看出它是一个Advisor,它重点有以下几个类型的成员变量:
Advice(通知):传入的实际类型为TransactionInterceptor,它是事务拦截器,实现了Advice接口,这个拦截器就相当于AOP中的通知,在执行目标方法前会进行拦截,进行事务处理;
TransactionAttributeSourcePointcut(切点):它实现了Pointcut和MethodMatcher接口,是一个切点,目标方法是否需要被事务代理就是通过它判断的;
TransactionAttributeSource:传入的实际类型为AnnotationTransactionAttributeSource,用于解析事务属性相关配置信息;
Advisor由Advice和Pointcut组成,现在Advice和Pointcut都已经知道了,接下来就去看看是如何判断当前Bean是否需要进行事务代理的。
事务底层是通过AOP实现的,所以它的处理逻辑与AOP类似,启动时会注册一个后置处理器,在postProcessAfterInitialization方法中判断是否需要进行代理,逻辑与AOP一致,会获取所有的Advisor,判断是否有匹配当前Bean的Advisor,Spring会自动为事务注册Advisor(BeanFactoryTransactionAttributeSourceAdvisor),匹配的处理逻辑在TransactionAttributeSourcePointcut切点中实现,是否匹配的判断条件如下:
- 判断当前Bean的Class是否匹配,具体是通过ClassFilter(TransactionAttributeSourceClassFilter)的matches方法实现的,注意这里并不是判断当前Bean所在类上面是否有事务注解,这个条件主要是为了排除一些Spring认为不需要进行事务代理的类,比如某个Bean的类路径以java.开头,而我们编写的类一般不会是以java开头的,所以这个Bean就会跳过代理,对于我们编写的Bean,一般不会被这个条件过滤掉,会进行下一个条件判断;
TransactionAttributeSourceClassFilter是TransactionAttributeSourcePointcut的内部类,里面有matches方法的实现。
- 判断当前Bean中的方法是否与事务切点匹配,具体是通过MethodMatcher(TransactionAttributeSourcePointcut)的matches方法实现,这里会获取当前Bean的所有方法,一个个与事务切点进行匹配,匹配规则如下:
(1)从方法中获取事务注解相关的设置;
(2)从方法所在类中获取事务注解相关设置;
(2)如果方法所在的类实现了接口,还会从接口上面解析是否有事务注解相关的配置;
如果我们使用了@Transactional注解对方法或者类进行了配置,就会在这一步解析到相关内容。
如果通过以上方式中的任意一种获取到了事务相关设置,就会认为当前Bean需要进行事务代理,为其创建代理对象,实现与AOP一致,会为其创建一个AOP代理对象,只不过在执行目标方法时,Spring会通过已经设定好的事务切面进行拦截,也就是BeanFactoryTransactionAttributeSourceAdvisor中的TransactionInterceptor对进行方法拦截,而在AOP中一般是我们自己编写切面。
事务拦截
上面我们知道对于需要进行事务拦截的Bean,会为其创建代理对象,在执行目标方法的时候,会进入事务拦截器的处理逻辑,主要步骤如下:
- 获取事务管理器;
- 创建事务;
- 这里主要是向后执行拦截器链,待所有的拦截器都执行完毕之后,执行目标方法;
- 捕捉异常,如果出现异常进行回滚;
- 提交事务;

事务的创建
事务的创建分为两部分:
一、 获取事务
(1)首先获取事务对象,它是一个抽象方法,数据源的不同具体的实现类也不同;
以DataSourceTransactionManager为例,它主要是创建了一个数据源事务对象(DataSourceTransactionObject),然后根据数据源信息源获取当前线程绑定的ConnectionHolder对象(如果有的话会获取到否则获取为空),ConnectionHolder中存有数据库连接及事务的活跃状态,之后会将这个ConnectionHolder设置到数据源事务对象中,将数据源事务对象返回;
(2)根据上一步获取到的事务对象,判断当前线程是否存在事务,如果存在事务需要根据事务传播行为进行不同的处理;
是否存在事务的判断方式是通过当前线程是否持有数据库连接(数据源事务对象中的ConnectionHolder不为空)并且事务处于活跃状态。
- 如果事务传播行为设是PROPAGATION_NEVER,表示不能存在事务,当前存在事务会抛出异常;
- 如果事务的传播行为是PROPAGATION_NOT_SUPPORTED,表示以不使用事务的方式执行,如果当前存在事务,则挂起当前的事务,执行完当前逻辑后(不使用事务)再恢复挂起的事务;
- 如果事务的传播行为是PROPAGATION_REQUIRES_NEW,表示每次执行都新建事务,如果当前存在事务需要挂起当前事务,创建一个自己的事务执行之后再恢复挂起的事务;
- 如果事务的传播行为是PROPAGATION_NESTED,表示嵌套事务,判断是否使用保存点,如果是则使用嵌套事务,否则开启一个新事务;
- 其他情况使用当前的事务;
(3)如果当前线程不存在事务:
如果事务的传播行为是PROPAGATION_MANDATORY,它要求必须存在事务,当前不存在事务,会抛出异常;
如果传播行为是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED,新建事务;
其他情况创建一个空事务;
新建事务说明之前不存在事务,ConnectionHolder为空,此时会从数据库连接池中获取一个连接,设置到ConnectionHolder中,并将当前线程对应这个ConnectionHolder与数据源绑定(底层ThreadLocal实现),上面第(1)步中可以看到会通过数据源获取当前线程的ConnectionHolder,数据就是在这里添加的,之后就可以通过这个判断当前线程是否已经存在事务。
二、 预处理事务
主要是进行事务相关信息的封装以及事务和线程的绑定。
事务回滚
当执行过程中出现异常时,会进行事务回滚,回滚的处理逻辑如下:
- 判断事务是否设置了保存点,如果设置了将事务回滚到保存点;
- 如果是一个独立的新事务,直接回滚即可;
- 如果既没有设置保存点,也不是一个新事务,说明可能处于嵌套事务中,此时只设置回滚状态rollbackOnly为true,当它的外围事务进行提交时,如果发现回滚状态为true,外围事务则不提交;
资源清理
在事务提交/回滚之后,需要根据情况清理相关的资源以及恢复被挂起的事务,主要有以下操作:
- 清除当前线程绑定的事务相关信息;
- 清除当前线程对应的ConnectionHolder与数据源的绑定关系及ConnectionHolder自身的清理;
- 如果挂起的事务不为空,恢复挂起的事务;
【Spring】事务实现原理的更多相关文章
- Spring 事务管理原理探究
此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...
- 关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.
主要以结果为导向解释Spring 事务原理,连接池的消耗,以及事务内开启事务线程要注意的问题. Spring 事务原理这里不多说,网上一搜一大堆,也就是基于AOP配合ThreadLocal实现. 这里 ...
- spring事务实现原理
实现原理 本质 如果你用过Spring AOP,那么理解注解事务就十分简单了.事务注解本质上实在事务方法加入一个Around切面,在方法开始前开始事务,在抛出异常后回滚事务.使用简单伪代码可以简单理解 ...
- spring 事务 @EnableTransactionManagement原理
@EnableXXX原理:注解上有个XXXRegistrar,或通过XXXSelector引入XXXRegistrar,XXXRegistrar实现了 ImportBeanDefinitionRegi ...
- 通俗的讲法理解spring的事务实现原理
拿房屋买卖举例,流程:销售房屋 -- 接待员 -- 销售员 -- 财务 售楼处 存放着所有待售和已售的房屋数据(数据源 datasource) 总经理 带领一套自己的班底,下属员工都听自己的,服务于售 ...
- Spring事务实现分析
一.Spring声明式事务用法 1.在spring配置文件中配置事务管理器 <bean id="baseDataSource" class="com.alibaba ...
- Spring事务的5种隔离级别和7种传播性
隔离级别 isolation,5 种: ISOLATION_DEFAULT,ISOLATION_READ_UNCOMMITTED,ISOLATION_READ_COMMITTED,ISOLATION_ ...
- Spring事务源码分析总结
Spring事务是我们日常工作中经常使用的一项技术,Spring提供了编程.注解.aop切面三种方式供我们使用Spring事务,其中编程式事务因为对代码入侵较大所以不被推荐使用,注解和aop切面的方式 ...
- Spring源码剖析9:Spring事务源码剖析
转自:http://www.linkedkeeper.com/detail/blog.action?bid=1045 声明式事务使用 Spring事务是我们日常工作中经常使用的一项技术,Spring提 ...
- 这一次搞懂Spring事务注解的解析
前言 事务我们都知道是什么,而Spring事务就是在数据库之上利用AOP提供声明式事务和编程式事务帮助我们简化开发,解耦业务逻辑和系统逻辑.但是Spring事务原理是怎样?事务在方法间是如何传播的?为 ...
随机推荐
- Django reset framework: 序列化
序列化与反序列化 将模型转换为json 称之为 序列化 将json转换为模型 称之为 反序列化 何时进行序列化与反序列化 序列化:当后端将数据库中信息取出返回给前端时,要进行序列化操作 反序列化:当需 ...
- 管于pyinstaller 打包完成后不能运行的问题
方案一: 进入项目路径,在cmd窗口输入python 文件名.之后查看结果,看是否有模块未安装,或者是未导入模块.因为pyinstaller打包时,是按照被打包文件上的导入的库名进行打包的,所以需要将 ...
- Django2.2:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 9737: illegal multibyte sequence
报错截图: 解决方案: 打开django/views下的debug.py文件,转到line331行: with Path(CURRENT_DIR, 'templates', 'technical_50 ...
- mysql根据mysqlbinlog恢复找回被删除的数据库
年初和朋友一起做了个项目,到现在还没收到钱呢,今天中午时候突然听说之前的数据库被攻击了,业务数据库全部被删除.看有没有什么办法恢复,要是恢复不了,肯定也别想拿钱了吧? README FOR RECOV ...
- 快速掌握Vue3:速成Vue3前端开发看这篇就够啦
一.Vue基本概念 1.1-Vue3的优点 Vue3支持Vue2额大多数特性. 更好的支持TypeScript. 打包大小减少41%. 初次渲染快55%,更新渲染快133%. 内存减少54%. 使用p ...
- AcWing 第 92 场周赛 C题 4866. 最大数量 题解
原题链接 链表 + 并查集乱搞做法: 思路 首先可以发现,想要让度数尽量大,那我们应该构造成菊花图,即下图所示: 对于每个需求,我们可以知道,如果之前他们没有连在一起,那我们一定得把他们连在一起,该过 ...
- [pandas]从多个文件中构建dataframe
按列从多个文件中构建 假设有两个csv文件,列不相同,需要整合为一个dataframe,使用glob模块: from glob import glob import pandas as pd # gl ...
- [HDCTF2019]Maze 反汇编-花指令处理
这是一道迷宫花指令加upx脱壳处理的题 先介绍花指令 一. 概述 花指令是对抗反汇编的有效手段之一,正常代码添加了花指令之后,可以破坏静态反汇编的过程,使反汇编的结果出现错误.错误的反汇编结果会造成破 ...
- vue3封装筛选项
背景 项目开发中遇到筛选项,并且几个页面都有使用,依次写,太过于繁琐 筛选项解构如下 封装全局组件fjj-content <template> <div class="fj ...
- 【反反爬】使用Jsoup爬取数据保存Excel
本文主要使用Jsoup爬取XXX房屋信息,抓取一些房屋信息,比如房屋楼盘.户型.价格.地址等信息,然后保存到Excel,便于对比和筛选,选出符合预期的好房. 注意,有些网站有防爬取机制,需要设置动 ...