zoukankan      html  css  js  c++  java
  • spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)

    写在前面

      由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交、回滚等操作全部交给它来实现

      先来看下三大接口

      • PlatformTransactionManager : 事务管理器

      • TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等

      • TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚

      一般我们给事务管理器的默认实现为DataSourceTransactionManager

        <!-- 事务管理器配置 -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>

    DataSourceTransactionManager(事务管理器接口定义PlatformTransactionManager)

    PlatformTransactionManager

    • AbstractPlatformTransactionManager
      •   DataSourceTransactionManager(重点)
      •   HibernateTransactionManager
      •   JpaTransactionManager
    public interface PlatformTransactionManager {
        //获取一个具体的事务状态信息
        TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
        //提交一个事务状态信息
        void commit(TransactionStatus status) throws TransactionException;
        //回滚一个事务状态信息
        void rollback(TransactionStatus status) throws TransactionException;
    }

    获取Object transaction:

      大体内容就是先获取上述说明(TransactionStatus)的Object transaction,判断当前事务是否已存在,如果存在则进行事务的传播属性处理,后面详细说明,如果不存在new DefaultTransactionStatus,新创建一个事务,同时使用Object transaction开启事务。 分成了几个过程:

      

    1. 获取Object transaction:不同的事务管理器获取不同的Object transaction

      DataSourceTransactionManager就是获取上述的DataSourceTransactionObject

      从当前线程中获取绑定的ConnectionHolder,可能为null,如果为null,则会在下一个开启事务的过程中,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程

    然后我们new 一个DataSourceTransactionObject了,具体过程如下:

        @Override
        protected Object doGetTransaction() {
            DataSourceTransactionObject txObject = new DataSourceTransactionObject();
            txObject.setSavepointAllowed(isNestedTransactionAllowed());
            ConnectionHolder conHolder =
                    (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
            txObject.setConnectionHolder(conHolder, false);
            return txObject;
        }

     

      HibernateTransactionManager获取HibernateTransactionObject

      从当前线程中获取绑定的SessionHolder,可能为null,如果为null,则会在下一个开启事务的过程中从sessionFactory中获取一个session,然后封装成SessionHolder,然后再绑定到当前线程

    然后我们就可以new 一个HibernateTransactionObject了,具体过程如下:

        @Override
        protected Object doGetTransaction() {
            HibernateTransactionObject txObject = new HibernateTransactionObject();
            txObject.setSavepointAllowed(isNestedTransactionAllowed());
    
            SessionHolder sessionHolder =
                    (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
            if (sessionHolder != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction");
                }
                txObject.setSessionHolder(sessionHolder);
            }
            else if (this.hibernateManagedSession) {
                try {
                    Session session = this.sessionFactory.getCurrentSession();
                    if (logger.isDebugEnabled()) {
                        logger.debug("Found Hibernate-managed Session [" + session + "] for Spring-managed transaction");
                    }
                    txObject.setExistingSession(session);
                }
                catch (HibernateException ex) {
                    throw new DataAccessResourceFailureException(
                            "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
                }
            }
    
            if (getDataSource() != null) {
                ConnectionHolder conHolder = (ConnectionHolder)
                        TransactionSynchronizationManager.getResource(getDataSource());
                txObject.setConnectionHolder(conHolder);
            }
    
            return txObject;
        }

      2. 构建DefaultTransactionStatus,使用Object transaction开启事务

      

      DataSourceTransactionManager的DataSourceTransactionObject开启过程如下:

      首先判断之前的获取当前线程绑定的ConnectionHolder是否为null,如果为null,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程因为开启了一个事务,则必须要关闭DataSourceTransactionObject中Connection的自动提交

        @Override
        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()) {
                    TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
                }
            }
    
            catch (Throwable ex) {
                if (txObject.isNewConnectionHolder()) {
                    DataSourceUtils.releaseConnection(con, this.dataSource);
                    txObject.setConnectionHolder(null, false);
                }
                throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
            }
        }

      HibernateTransactionManager的HibernateTransactionObject开启过程如下:

    也是同样的逻辑,如果SessionHolder为null,则从SessionFactory中获取一个Session,然后封装成SessionHolder,然后把这个SessionHolder绑定到当前线程

      3. 第二个接口:void rollback(TransactionStatus status) 回滚事务

      回滚,则还是利用DefaultTransactionStatus内部的Object transaction来执行回滚操作

      DataSourceTransactionManager就是使用DataSourceTransactionObject中的Connection来进行回滚操作

        @Override
        protected void doRollback(DefaultTransactionStatus status) {
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
            Connection con = txObject.getConnectionHolder().getConnection();
            if (status.isDebug()) {
                logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
            }
            try {
                con.rollback();
            }
            catch (SQLException ex) {
                throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
            }
        }

      

      HibernateTransactionManager就是使用HibernateTransactionObject中的SessionHolder中的Session创建的事务Transaction来进行回滚操作

        @Override
        protected void doRollback(DefaultTransactionStatus status) {
            HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
            if (status.isDebug()) {
                logger.debug("Rolling back Hibernate transaction on Session [" +
                        txObject.getSessionHolder().getSession() + "]");
            }
            try {
                txObject.getSessionHolder().getTransaction().rollback();
            }
            catch (org.hibernate.TransactionException ex) {
                throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
            }
            catch (HibernateException ex) {
                // Shouldn't really happen, as a rollback doesn't cause a flush.
                throw convertHibernateAccessException(ex);
            }
            finally {
                if (!txObject.isNewSession() && !this.hibernateManagedSession) {
                    // Clear all pending inserts/updates/deletes in the Session.
                    // Necessary for pre-bound Sessions, to avoid inconsistent state.
                    txObject.getSessionHolder().getSession().clear();
                }
            }
        }

      4.第三个接口: void commit(TransactionStatus status) 提交事务

      同理,DataSourceTransactionManager依托内部的Connection来完成提交操作

      HibernateTransactionManager依托内部的Transaction来完成提交操作

  • 相关阅读:
    移动运营四:如何优化页面布局
    移动运营三:如何进行场景洞察
    移动运营二:如何更加了解你的用户
    移动运营一:如何进行运营效果分析
    操作系统的系统调用
    从图灵机到操作系统的启动
    伸展树(splay tree)
    AVL树
    二叉搜索树
    表达式树
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6760229.html
Copyright © 2011-2022 走看看