zoukankan      html  css  js  c++  java
  • spring事务传播实现源码分析

     

           本文只是对spring事务传播实现的流程进行简单的分析,如有不对之处请指出。

           配置spring事务管理时,我们会使用DataSourceTransactionManager这个类,它继承了AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager实现了PlatformTransactionManager接口,PlatformTransactionManager接口是spring事务管理的基础接口,只有三个方法getTransaction()、commit()和rollback()。
            通过注解@Transactional,我们就可以把事务交由spring管理。spring是通过代理的方式对其添加事务管理,在生成的代理对象中就会调用PlatformTransactionManager实现类的三个方法来获取事务、提交事务、回滚事务,从而达到事务管理的目的。其中获取事务即调用getTransaction()方法,改方法中就会对事务的传播做相应的处理。

    1、getTransaction()方法

    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        Object transaction = doGetTransaction(); // 获取事务管理对象,从下面doGetTransaction()实现可以知道,这里是尝试获取已有的事务管理对象,这里已有的就是指“传播”来的事务。

        ..............................

        if (isExistingTransaction(transaction)) { //判断该事务管理对象是否已经存在
            // Existing transaction found -> check propagation behavior to find out how to behave.
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

     ..................................

        // No existing transaction found -> check propagation behavior to find out how to proceed.

       // 根据不同事务传播属性进行不同的处理
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }
        else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            SuspendedResourcesHolder suspendedResources = suspend(null);
            if (debugEnabled) {
                logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
            }
            try {
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                doBegin(transaction, definition); // 新起一个事务
                prepareSynchronization(status, definition);
                return status;
            }
            catch (RuntimeException ex) {
                resume(null, suspendedResources);
                throw ex;
            }
            catch (Error err) {
                resume(null, suspendedResources);
                throw err;
            }
        }
        else {
            // Create "empty" transaction: no actual transaction, but potentially synchronization.
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
        }
    }

    2、 doGetTransaction()方法

    protected Object doGetTransaction() {
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        txObject.setSavepointAllowed(isNestedTransactionAllowed());

        // TransactionSynchronizationManager里面通过ThreadLocal变量保存了dataSource对应的ConnectionHolder ,如果ConnectionHolder存在且激活就表明有“传播”来的事务。
        ConnectionHolder conHolder =
            (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); 

        // 顺便提下,其它ORM框架就是通过TransactionSynchronizationManager.getResource(dataSource)获取数据库连接,以此到达事务交由spring管理的目的。
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

    3、 isExistingTransaction()方法
    protected boolean isExistingTransaction(Object transaction) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

        //ConnectionHolder存在且激活就表明有“传播”来的事务。
        return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
    }

    4、 doBegin()方法

    // 这里是新起一个事务,为事务管理对象设置相应的值,包括ConnectionHolder、隔离等级、是否自动提交等,并把当前线程与ConnectionHolder和dataSource进行绑定。

    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            if (txObject.getConnectionHolder() == null ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.getConnection();
                if (logger.isDebugEnabled()) {
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }

            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            con = txObject.getConnectionHolder().getConnection();

            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);

            // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
            // so we don't want to do it unnecessarily (for example if we've explicitly
            // configured the connection pool to set it already).
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);

            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            // Bind the session holder to the thread.
            if (txObject.isNewConnectionHolder()) {

                //把当前线程与ConnectionHolder和dataSource进行绑定,在上面的doGetTransaction()中就可以对应获取,即到达事务传播的目的。
                TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
            }
        }

        catch (Throwable ex) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }

  • 相关阅读:
    java经常出现的异常
    后台采用springmvc框架 前台bootstrap 实现对话框编辑信息
    List集合与Array数组之间的互相转换
    freemarker 设置文本内容超过一定长度 用省略号代替
    bootstrap实现多个下拉框同时搜索
    jquery 循环遍历选中的多选复选框checkbox
    同时对数据库进行更新,添加与删除操作
    获取页面内容封装成json对象
    前台bootstrap按钮动态添加与删除
    set 遍历
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/10712740.html
Copyright © 2011-2022 走看看