30张图带你分析:spring事务源码

2020-10-26  本文已影响0人  Java旺

前言

很多人认为事务很简单,但是往往在工作中遇到一些事务的坑(尤其是事务方法中嵌套其它事务方法一起使用时)之后,我们却不知道问题产生的原因和如何有效的解决。

这就需要去分析 Spring的核心源码 ,最终踏实地找到问题的原因和解决思路。

注解事务运行流程

先来看Spring事务的底层运行流程

30张图带你分析:spring事务源码

核心对象关系

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

一、事务配置相关

TransactionManagementConfigurationSelector :配置启动事务启动(EnableTransactionManagement)时,导入注册的配置bean。

它包括AutoProxyRegistrar和ProxyTransactionManagementConfiguration两大配置块。

AutoProxyRegistrar :负责依赖注入事务的相关属性配置和注入事务入口类(InfrastructureAdvisorAutoProxyCreator类);

ProxyTransactionManagementConfiguration :负责注入事务相关的Bean, 包括:

二、事务运行拦截相关

源码实现

接下来我们来分块分析一下,Spring事务的源码,其中的一些坑和重要结论会在这个过程分享。

一、事务配置

TransactionManagementConfigurationSelector.selectImports()负责定义外部加入spring容器的配置类

30张图带你分析:spring事务源码

此方法最终在ConfigurationClassParser中被解析并最终实例化为bean

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

AutoProxyRegistrar.registerBeanDefinitions()把InfrastructureAdvisorAutoProxyCreator注册beandefinition

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

ProxyTransactionManagementConfiguration.transactionAdvisor()注入事务切面

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

二、事务创建

实际运行入口之一(还有cglib):JdkDynamicAopProxy..invoke()

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

ReflectiveMethodInvocation.proceed()切面调用链处理核心方法

30张图带你分析:spring事务源码

TransactionInterceptor.invoke()从这里触发事务拦截

30张图带你分析:spring事务源码

TransactionAspectSupport.invokeWithinTransaction()实现Spring事务的核心业务

30张图带你分析:spring事务源码

TransactionAspectSupport.determineTransactionManager()定义指定的事务管理器

30张图带你分析:spring事务源码

对于事务管理器,默认使用DataSourceTransactionManager(可配置数据源的事务管理器),也可自定义事务管理器,然后配置数据源即可。

createTransactionIfNecessary()创建事务信息TransactionInfo:其中包括数据源、事务连接(ConnectionHolder)、事务状态、连接缓存等;

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

DataSourceTransactionManager.doGetTransaction()获取事务对象:里面包含连接包装和缓存

30张图带你分析:spring事务源码

TransactionSynchronizationManager.getResource()连接线程级缓存:确保当前线程拿到唯一的数据连接

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

AbstractPlatformTransactionManager.startTransaction()开启一个新事务

30张图带你分析:spring事务源码

只有newTransaction为true时,spring才会做实际的提交或回滚,这里是一个很重要的点。很多嵌套事务的坑,都是这里没有理解清楚。

DataSourceTransactionManager.doBegin()开启事务核心源码

30张图带你分析:spring事务源码

TransactionSynchronizationManager.bindResource()设置当前连接和数据源的线程级绑定

30张图带你分析:spring事务源码

三、事务回滚

对于非编程式事务而言,Spring事务的核心实现其实就是用try / catch 包裹事务提交和回滚的范式而已,但提交和回滚里面的包装大有讲究。

TransactionAspectSupport.completeTransactionAfterThrowing()事务回滚实现

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

以上截图中doSetRollbackOnly(),不会在连接上实际设置回滚点,只打个标记(当前事务需要回滚, commit时会使用该标记)!

四、事务提交

AbstractPlatformTransactionManager.commit()事务实际提交源码这里

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

cleanupAfterCompletion()回收连接或恢复事务,这个点耐人寻味:当事务传播属性为Require_New时,会暂时挂起之前的连接,然后创建新连接;当新连接提交或回滚后,通过这个方法恢复之前连接和状态!!!!

30张图带你分析:spring事务源码 30张图带你分析:spring事务源码 30张图带你分析:spring事务源码

OK事务到这里,我根据源码分享一些关于嵌套子事务的甜点:

总结

今天的Spring事务源码就暂时分享到这里,事务这块只有一层的事务很简单,但当嵌套了多个(层)子事务(而且每个子事务的事务传播属性可能不一样的情况下)时就当另当别论了。

需要我们根据源码的规律去分析每层子事务该如何流转!!所以需要把这块的源码搞熟,遇到复杂的嵌套事务分析原因,那问题就不大了。

来源:https://www.tuicool.com/articles/YvaIfmF

上一篇下一篇

猜你喜欢

热点阅读