美文网首页
30张图带你分析:spring事务源码

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

作者: Java旺 | 来源:发表于2020-10-26 14:36 被阅读0次

    前言

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

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

    注解事务运行流程

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

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

    核心对象关系

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

    一、事务配置相关

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

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

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

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

    • 事务切面Bean(BeanFactoryTransactionAttributeSourceAdvisor)
    • TransactionAttributeSource(事务配置属性bean)
    • TransactionInterceptor(事务拦截器bean);

    二、事务运行拦截相关

    • AopProxy:Spring AOP 动态代理的基接口,负责定义Proxy的基础行为;
    • MethodInterceptor:Spring AOP调用链中拦截器的内部核心接口,所有类型的切面最终都会最终包装成此接口触发统一拦截;
    • TransactionInterceptor:Spring事务拦截器的核心业务实现,AOP调用链也最终触发它的invoke方法;
    • TransactionManager:Spring管理的基接口,作为子接口上层接口区分,并没有定义实际的事务行为能力;
    • PlatformTransactionManager:继承TransactionManager,定义事务和基础行为;
    • AbstractPlatformTransactionManager:负责实现整个事务管理和运行过程中的公共行为和通用实现逻辑,它继承至PlatformTransactionManager接口;

    源码实现

    接下来我们来分块分析一下,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事务到这里,我根据源码分享一些关于嵌套子事务的甜点:

    • 嵌套事务过程,中间有任何异常,只要没被屏蔽,则都会上抛,不会再执行后续代码;
    • 只要设置Require_New事务传播属性,则每个Transactional注解方法内部都会单独提交或回滚;
    • 嵌套事务会在除首个Transactional注解外的子事务中创建savepoint回滚点;
    • 设置savepoint回滚点后,回滚时会回滚包括当前方法之前的所有事务;若只需回滚当前方法,则在最外层事务方法加try{}catch(){//不抛出异常};
    • 每个事务的对象都是不一样的,事务状态可能不一样,但连接可能是同一个;

    总结

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

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

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

    相关文章

      网友评论

          本文标题:30张图带你分析:spring事务源码

          本文链接:https://www.haomeiwen.com/subject/wwpamktx.html