天天看点

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

文章目录

  • ​​1.Spring 事务工作流程​​
  • ​​2.Spring 事务源码分析​​
  • ​​2.1 创建代理对象​​
  • ​​3.Spring 事务执行分析​​
  • ​​3.1 事务执行源码分析​​

1.Spring 事务工作流程

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

事务处理:

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

2.Spring 事务源码分析

refresh()

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

finishBeanFactoryInitialization()

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

preInstantiateSingletons()

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

doGetBean()

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

doCreateBean()

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

initializeBean()

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

applyBeanPostProcessorsAfterInitialization()

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

2.1 创建代理对象

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

获取切面列表

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

findCandidateAdvisors()

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

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

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

canApply(): 匹配对应的切面

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

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

getTransactionAttribute()

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

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

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

getTransactionAttribute()

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

创建Aop对象

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

3.Spring 事务执行分析

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

Cglib 代理对象进行

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

3.1 事务执行源码分析

Spring Tx (九) (Spring 事务源码分析)
  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 {
          // 这里不是我们的重点,省略...
        }
    }      

invokeWithinTransaction() 中获取事务的入口

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

从 attributeCache 获取事务的缓存数据

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

创建事务

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

获取事务状态

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

doGetTransaction(): 获取事务

Spring Tx (九) (Spring 事务源码分析)
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);
        }
    }      

invokeWithinTransaction() 获取到txInfo 对象

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

执行逻辑

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

回滚事务

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

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