• Spring Tx (九) (Spring 事务源码分析)


    1.Spring 事务工作流程

    在这里插入图片描述

    1. 获取到切面方法, 和所有切面匹配, 事务属性放入缓存attributeCache
    2. 创建Aop代理对象, 选择Jdk 和 Cglib

    在这里插入图片描述
    事务处理:

    1. 缓存拿到事务属性
    2. 创建并开启事务
    3. 执行业务逻辑
    4. 提交或者回滚事务

    2.Spring 事务源码分析

    refresh()

    在这里插入图片描述

    finishBeanFactoryInitialization()

    在这里插入图片描述

    preInstantiateSingletons()

    在这里插入图片描述

    在这里插入图片描述

    doGetBean()

    在这里插入图片描述

    doCreateBean()

    在这里插入图片描述

    initializeBean()

    在这里插入图片描述

    在这里插入图片描述

    applyBeanPostProcessorsAfterInitialization()

    在这里插入图片描述

    2.1 创建代理对象

    在这里插入图片描述

    在这里插入图片描述

    获取切面列表

    在这里插入图片描述

    findCandidateAdvisors()

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    findEligibleAdvisors(): 开始匹配对应的切面

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    canApply(): 匹配对应的切面

    在这里插入图片描述

    在这里插入图片描述

    如果匹配了, 会将事务的属性加入到attributeCache缓存中

    getTransactionAttribute()

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    从 element 对象中获取到@Transactional 注解

    在这里插入图片描述

    在这里插入图片描述

    getTransactionAttribute()

    在这里插入图片描述

    创建Aop对象

    在这里插入图片描述

    3.Spring 事务执行分析

    在这里插入图片描述

    Cglib 代理对象进行

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    3.1 事务执行源码分析

    在这里插入图片描述

    1. 从缓存中获取事务相关属性
    2. 创建事务: 获取事务, 设置事务属性, 开启事务
    3. 执行业务逻辑
    4. 回滚事务: 判断异常类型判断是否回滚, 执行回滚
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
                final InvocationCallback invocation) throws Throwable {
    
            //获取我们的事务属源对象
            TransactionAttributeSource tas = getTransactionAttributeSource();
            //通过事务属性源对象获取到我们的事务属性信息
            final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
            //获取我们配置的事务管理器对象
            final PlatformTransactionManager tm = determineTransactionManager(txAttr);
            //从tx属性对象中获取出标注了@Transactionl的方法描述符
            final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    
            //处理声明式事务
            if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
                //有没有必要创建事务
                TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
    
                Object retVal;
                try {
                    //调用钩子函数进行回调目标方法
                    retVal = invocation.proceedWithInvocation();
                }
                catch (Throwable ex) {
                    //抛出异常进行回滚处理
                    completeTransactionAfterThrowing(txInfo, ex);
                    throw ex;
                }
                finally {
                    //清空我们的线程变量中transactionInfo的值
                    cleanupTransactionInfo(txInfo);
                }
                //提交事务
                commitTransactionAfterReturning(txInfo);
                return retVal;
            }
            //编程式事务
            else {
              // 这里不是我们的重点,省略...
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    invokeWithinTransaction() 中获取事务的入口

    在这里插入图片描述

    从 attributeCache 获取事务的缓存数据

    在这里插入图片描述

    创建事务

    在这里插入图片描述

    在这里插入图片描述

    获取事务状态

    在这里插入图片描述

    doGetTransaction(): 获取事务

    在这里插入图片描述

    protected void doBegin(Object transaction, TransactionDefinition definition) {
            //强制转化事务对象
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
            Connection con = null;
    
            try {
                //判断事务对象没有数据库连接持有器
                if (!txObject.hasConnectionHolder() ||
                        txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                    //通过数据源获取一个数据库连接对象
                    Connection newCon = obtainDataSource().getConnection();
                    if (logger.isDebugEnabled()) {
                        logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                    }
                    //把我们的数据库连接包装成一个ConnectionHolder对象 然后设置到我们的txObject对象中去
                    txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
                }
    
                //标记当前的连接是一个同步事务
                txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
                con = txObject.getConnectionHolder().getConnection();
    
                //为当前的事务设置隔离级别
                Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
                txObject.setPreviousIsolationLevel(previousIsolationLevel);
    
                //关闭自动提交
                if (con.getAutoCommit()) {
                    txObject.setMustRestoreAutoCommit(true);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                    }
                    con.setAutoCommit(false);
                }
    
                //判断事务为只读事务
                prepareTransactionalConnection(con, definition);
                //设置事务激活
                txObject.getConnectionHolder().setTransactionActive(true);
    
                //设置事务超时时间
                int timeout = determineTimeout(definition);
                if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                    txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
                }
    
                // 绑定我们的数据源和连接到我们的同步管理器上   把数据源作为key,数据库连接作为value 设置到线程变量中
                if (txObject.isNewConnectionHolder()) {
                    TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
                }
            }
    
            catch (Throwable ex) {
                if (txObject.isNewConnectionHolder()) {
                    //释放数据库连接
                    DataSourceUtils.releaseConnection(con, obtainDataSource());
                    txObject.setConnectionHolder(null, false);
                }
                throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    invokeWithinTransaction() 获取到txInfo 对象

    在这里插入图片描述

    执行逻辑

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    回滚事务

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    如果抛出的异常类型,和事务定义的异常类型匹配,证明该异常需要捕获。

    之所以用递归,不仅需要判断抛出异常的本身,还需要判断它继承的父类异常,满足任意一个即可捕获。

    在这里插入图片描述

  • 相关阅读:
    Hive(20):Hive的函数之窗口函数
    Mac监控键盘输入并执行动作
    InternImage
    线上流量卡申请须知
    前端网站分享
    mysql中max_connections与max_user_connections使用区别
    计算机毕业设计java+ssm医院医疗救助系统的设计与实现
    Linux_用户组管理
    k8s1.19使用ceph14
    基于微信小程序的校园生活管理系统设计与实现(源码+lw+部署文档+讲解等)
  • 原文地址:https://blog.csdn.net/qq_43141726/article/details/127625108