• spring---transaction(4)---源代码分析(事务的状态TransactionStatus)


    写在前面

      TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承

      TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装(Spring利用保存点功能实现了事务的嵌套功能。后面会详细说明)

    public interface SavepointManager {
        Object createSavepoint() throws TransactionException;
        void rollbackToSavepoint(Object savepoint) throws TransactionException;
        void releaseSavepoint(Object savepoint) throws TransactionException;
    }
    public interface TransactionStatus extends SavepointManager, Flushable {
        //是否是一个新的事物
        boolean isNewTransaction();
        //是否有保存点
        boolean hasSavepoint();
        void setRollbackOnly();
        //是否已被标记为回滚
        boolean isRollbackOnly();
    @Override
    void flush(); boolean isCompleted(); }

    DefaultTransactionStatus

    常用的TransactionStatus接口实现为DefaultTransactionStatus:

    public class DefaultTransactionStatus extends AbstractTransactionStatus {
    
        private final Object transaction;
    
        private final boolean newTransaction;
    
        private final boolean newSynchronization;
    
        private final boolean readOnly;
    
        private final boolean debug;
    
        private final Object suspendedResources;
    }

      目前jdbc事务是通过Connection来实现事务的,Hibernate是通过它自己定义的Transaction来实现的,所以各家的事务都不同,所以Spring只能以Object transaction的形式来表示各家的事务,事务的回滚和提交等操作都会最终委托给上述Object transaction来完成。

      Object transaction的职责就是提交回滚事务,这个transaction的选择可能如下:

      • DataSourceTransactionObject
      • HibernateTransactionObject
      • JpaTransactionObject

      详细信息分别如下:

    • DataSourceTransactionObject:

        我们使用了dataSource来获取连接,要想实现事务功能,必然需要使用Connection,所以它中肯定有一个Connection来执行事务的操作。DataSourceTransactionObject中有一个ConnectionHolder,它封装了一个Connection。

    • HibernateTransactionObject:

        我们使用了hibenrate,此时要想实现事务功能,必然需要通过hibernate自己定义的Transaction来实现。

    HibernateTransactionObject中含有一个SessionHolder,和上面的ConnectionHolder一样,它封装了一个Session,有了Session,我们就可以通过Session来产生一个Hibernate的Transaction,从而实现事务操作。

    DefaultTransactionStatus的获取

      DefaultTransactionStatus的获取是事务管理器的方法,这里的实现是AbstractPlatformTransactionManager提供的模板方法

      在获取Object transaction之后,先进行判断,是否是已存在的事务。因为这个Object transaction的获取过程就是直接从线程绑定的获取的,可能当前线程已经存在事务

        @Override
        public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
         //获取相应的Object transaction Object transaction
    = doGetTransaction();      //就是依据和当前线程绑定的ConnectionHolder中是否已存在事务(也是依据和当前线程绑定的SessionHolder是否已存在事务) if (isExistingTransaction(transaction)) {
           //如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法:
    return handleExistingTransaction(definition, transaction, debugEnabled); }
         ... }

     

      如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法

        private TransactionStatus handleExistingTransaction(
                TransactionDefinition definition, Object transaction, boolean debugEnabled)
                throws TransactionException {
         // PROPAGATION_NEVER:不允许存在事务,如果存在抛出异常
            if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
                throw new IllegalTransactionStateException(
                        "Existing transaction found for transaction marked with propagation 'never'");
            }
         // PROPAGATION_NOT_SUPPORTED:不支持事务,如果存在事务,则需将事务挂起,保存起来,当执行完成之后,需要将挂起的事务继续恢复
            if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
                if (debugEnabled) {
                    logger.debug("Suspending current transaction");
                }
                Object suspendedResources = suspend(transaction);
                boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
                return prepareTransactionStatus(
                        definition, null, false, newSynchronization, debugEnabled, suspendedResources);
            }
         //PROPAGATION_REQUIRES_NEW:开启一个新的事务,如果当前存在事务则把当前事务挂起来
            if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
                if (debugEnabled) {
                    logger.debug("Suspending current transaction, creating new transaction with name [" +
                            definition.getName() + "]");
                }
                SuspendedResourcesHolder suspendedResources = suspend(transaction);
                try {
                    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                    DefaultTransactionStatus status = newTransactionStatus(
                            definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
             //可以看到,创建新的事务,就会调用doBegin(transaction, definition);方法,将事务开启。 doBegin(transaction, definition); prepareSynchronization(status, definition);
    return status; } catch (RuntimeException beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } catch (Error beginErr) { resumeAfterBeginException(transaction, suspendedResources, beginErr); throw beginErr; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
         //PROPAGATION_SUPPORTS 和 PROPAGATION_REQUIRED 如果当前存在事务,则仍旧使用该事物  
    if (debugEnabled) { logger.debug("Participating in existing transaction"); } if (isValidateExistingTransaction()) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }

      

      事务的挂起

      对于DataSourceTransactionManager来说,事务的挂起,就是把当前线程关联的ConnectionHolder解除绑定、同理事务的恢复就是把上述ConnectionHolder再重新绑定到当前线程,继续执行该事务

        @Override
        protected Object doSuspend(Object transaction) {
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
            txObject.setConnectionHolder(null);
    //解除绑定dataSource, conHolder 至 TransactionSynchronizationManager ConnectionHolder conHolder
    = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(this.dataSource); return conHolder; } @Override protected void doResume(Object transaction, Object suspendedResources) { ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
         //重新绑定dataSource, conHolder 至 TransactionSynchronizationManager TransactionSynchronizationManager.bindResource(
    this.dataSource, conHolder); }
  • 相关阅读:
    event.preventDefault() 火狐下没有作用。
    输入框禁止键盘输入数字意外的字符
    js遍历数组重复值和数组中对象重复值
    js获取30、X天前得时间
    docker 命令详解
    右键禁止浏览器自带的右键
    Kncokout之绑定事件三
    转:Maven的默认中央仓库以及修改默认仓库&配置第三方jar包从私服下载
    异常: java.security.InvalidKeyException: Illegal key size
    转:Java并发编程:深入剖析ThreadLocal
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6760317.html
Copyright © 2020-2023  润新知