Spring5.X 事务管理器 PlatformTransactionManager

一、事务管理器类图

Spring5.X 事务管理器 PlatformTransactionManager_第1张图片

 

二、事务管理器概述

PlatformTransactionManager接口定义了获取事务(getTransaction)、提交事务(commit)、回滚事务(rollback)三个方法。

getTransaction:根据指定的传播行为,返回当前活动的事务或创建新的事务。

commit:提交给定事务的提交。如果已通过编程将事务标记为仅回滚,请执行回滚。

rollback:执行给定事务的回滚。

以下是AbstractPlatformTransactionManager类中的获取事务、提交事务、回滚事务介绍。

 

三、创建事务 getTransaction

3.1 获取事务 getTransaction

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {

 // 获取事务,留给子类实现

 Object transaction = doGetTransaction();

 

 // Cache debug flag to avoid repeated checks.

 boolean debugEnabled = logger.isDebugEnabled();

 

 if (definition == null) {

  // 如果未提供事务定义,使用默认值。

  definition = new DefaultTransactionDefinition();

 }

 

 // 事务是否存在,留给子类实现

 if (isExistingTransaction(transaction)) {

  // 存在事务transaction->根据事务传播行为执行检查并返回TransactionStatus。

  return handleExistingTransaction(definition, transaction, debugEnabled);

 }

 

 // 超时时间小于默认值抛异常

 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {

  throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());

 }

 

 // 当前不存在事务且事务传播行为是TransactionDefinition.PROPAGATION_MANDATORY,则抛出异常

 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 | Error ex) {

   resume(null, suspendedResources);

   throw ex;

  }

 }

 else {

  // 创建“空”事务:没有实际的事务,但是可能是同步的。

  if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {

   logger.warn("Custom isolation level specified but no actual transaction initiated; " +

     "isolation level will effectively be ignored: " + definition);

  }

  boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);

  // 创建并初始化事务

  return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);

 }

}

 

3.2 处理存在的事务并返回TransactionStatus handleExistingTransaction

PROPAGATION_REQUIRES_NEW

表示当前方法必须在它自己的事务里运行,一个新的事务将被启动,而如果有一个事务正在运行的话,则在这个方法运行期间被挂起。而.Spring中对于此种传播方式的处理与新事务建立最大的不同点在于使用suspend方法将

原事务挂起。将信息挂起的目的当然是为了在当前事务执行完毕后在将原事务还原。

PROPAGATION_NESTED

表示如果当前正有一个事务在运行中,则该方法应该运行在一个嵌套的事务中,被嵌套的事务可以独立于封装事务进行提交或者回滚,如果封装事务不存在,行为就像PROPAGATION_ REQUIRES_ NEW。对于嵌入式事务的处理, Spring ;中主要考虑了两种方式的处理。

Spring中允许嵌入事务的时候,则首选设置保存点的方式作为异常处理的回滚。

对于其他方式,比如JTA无法使用保存点的方式,那么处理方式与PROPAGATION_REQUIRES_NEW相同,而一旦出现异常,则由Spring的事务异常处理机制去完成后续操作。

 

private TransactionStatus handleExistingTransaction(

  TransactionDefinition definition, Object transaction, boolean debugEnabled)

  throws TransactionException {

 

 // 存在事务且事务传播行为是TransactionDefinition.PROPAGATION_NEVER,则抛出异常

 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {

  throw new IllegalTransactionStateException(

    "Existing transaction found for transaction marked with propagation 'never'");

 }

 

 // 事务传播行为是TransactionDefinition.PROPAGATION_NOT_SUPPORTED,将当前存在的事务挂起,非事务模式执行

 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {

  if (debugEnabled) {

   logger.debug("Suspending current transaction");

  }

  // 将当前存在的事务挂起

  Object suspendedResources = suspend(transaction);

  // SYNCHRONIZATION_ALWAYS支持PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER

  boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);

  return prepareTransactionStatus(

    definition, null, false, newSynchronization, debugEnabled, suspendedResources);

 }

 

 // 事务传播行为是TransactionDefinition.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);

   // 初始化事务信息

   prepareSynchronization(status, definition);

   return status;

  }

  catch (RuntimeException | Error beginEx) {

   resumeAfterBeginException(transaction, suspendedResources, beginEx);

   throw beginEx;

  }

 }

 

 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()) {

   // 通过TransactionStatus实现的SavepointManager API在现有的Spring管理的事务中创建保存点。 通常使用JDBC 3.0保存点。从不激活Spring同步。

   DefaultTransactionStatus status =

     prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);

   // 创建并保存Savepoint

   status.createAndHoldSavepoint();

   return status;

  }

  else {

   // 通过嵌套的begin和commit /rollback调用进行嵌套事务。 通常仅用于JTA:如果存在预先存在的JTA事务,则可以在此处激活Spring同步。有些情况是不能使用保存点操作,比如JTA那么建立新事务

   boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

   DefaultTransactionStatus status = newTransactionStatus(

     definition, transaction, true, newSynchronization, debugEnabled, null);

   // 根据给定的事务定义开始具有语义的新事务。留给子类实现

   doBegin(transaction, definition);
   // 初始化事务信息:newSynchronization = true 新的事务同步则激活事务同步

   prepareSynchronization(status, definition);

   return status;

  }

 }

 

 // Assumably PROPAGATION_SUPPORTS or 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);

}

 

3.3 挂起事务 suspend

挂起操作的主要目的是记录原有事务的状态,以便于后续操作对事务的恢复。

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {

 if (TransactionSynchronizationManager.isSynchronizationActive()) {

  List suspendedSynchronizations = doSuspendSynchronization();

  try {

   Object suspendedResources = null;

   if (transaction != null) {

    // 留给子类实现

    suspendedResources = doSuspend(transaction);

   }

   String name = TransactionSynchronizationManager.getCurrentTransactionName();

   TransactionSynchronizationManager.setCurrentTransactionName(null);

   boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();

   TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);

   Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();

   TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);

   boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();

   TransactionSynchronizationManager.setActualTransactionActive(false);

   return new SuspendedResourcesHolder(

     suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);

  }

  catch (RuntimeException | Error ex) {

   // doSuspend失败-原始事务恢复活动状态...

   doResumeSynchronization(suspendedSynchronizations);

   throw ex;

  }

 }

 else if (transaction != null) {

  // 事务处于活动状态,但没有同步活动。

  Object suspendedResources = doSuspend(transaction);

  return new SuspendedResourcesHolder(suspendedResources);

 }

 else {

  // 事务或同步均未激活。

  return null;

 }

}

 

3.4 创建新的事务TransactionStatus并初始化 prepareTransactionStatus

protected final DefaultTransactionStatus prepareTransactionStatus(

  TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,

  boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

 

 DefaultTransactionStatus status = newTransactionStatus(

   definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);

 prepareSynchronization(status, definition);

 return status;

}

 

3.5 创建TransactionStatus newTransactionStatus

protected DefaultTransactionStatus newTransactionStatus(

  TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,

  boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

 

 boolean actualNewSynchronization = newSynchronization &&

   !TransactionSynchronizationManager.isSynchronizationActive();

 return new DefaultTransactionStatus(

   transaction, newTransaction, actualNewSynchronization,

   definition.isReadOnly(), debug, suspendedResources);

}

 

3.6 新创建的事务信息记录在当前线程中 prepareSynchronization

protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {

 if (status.isNewSynchronization()) {

  TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());

  TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(

    definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?

      definition.getIsolationLevel() : null);

  TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());

  TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());

  // 激活当前线程的事务同步

  TransactionSynchronizationManager.initSynchronization();

 }

}

 

3.7 挂起当前线程所有事务同步,并取消激活当前线程的事务同步 doSuspendSynchronization

private List doSuspendSynchronization() {

 // 获取当前线程所有事务同步

 List suspendedSynchronizations =

   TransactionSynchronizationManager.getSynchronizations();

 // 挂起当前线程所有事务同步

 for (TransactionSynchronization synchronization : suspendedSynchronizations) {

  synchronization.suspend();

 }

 

 // 取消激活当前线程的事务同步 

 TransactionSynchronizationManager.clearSynchronization();

 return suspendedSynchronizations;

}

 

3.8 重新激活当前线程的事务同步,并恢复所有给定的事务同步 doResumeSynchronization

private void doResumeSynchronization(List suspendedSynchronizations) {

 // 重新激活当前线程的事务同步

 TransactionSynchronizationManager.initSynchronization();

 

 // 恢复所有给定的事务同步

 for (TransactionSynchronization synchronization : suspendedSynchronizations) {

  synchronization.resume();

  TransactionSynchronizationManager.registerSynchronization(synchronization);

 }

}

 

3.9 内部事务开始失败后恢复外部事务 resumeAfterBeginException

private void resumeAfterBeginException(

  Object transaction, @Nullable SuspendedResourcesHolder suspendedResources, Throwable beginEx) {

 String exMessage = "Inner transaction begin exception overridden by outer transaction resume exception";

 try {

  resume(transaction, suspendedResources);

 }

 catch (RuntimeException | Error resumeEx) {

  logger.error(exMessage, beginEx);

  throw resumeEx;

 }

}

 

3.10 恢复挂起的事务和事务同步 resume

protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)

  throws TransactionException {

 

 if (resourcesHolder != null) {

  Object suspendedResources = resourcesHolder.suspendedResources;

  if (suspendedResources != null) {

   // 留给子类实现

   doResume(transaction, suspendedResources);

  }

  List suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;

  if (suspendedSynchronizations != null) {

   TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);

 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);

   TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);

   TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);

   // 传送门:3.8

   doResumeSynchronization(suspendedSynchronizations);

  }

 }

}

 

四、提交事务 commit

4.1 提交事务流程

在真正的数据提交之前,还需要做个判断。不知道大家还有没有印象,在我们分析事务异常处理规则的时候,当某个事务既没有保存点又不是新事务,Spring 对它的处理方式只是设置一个回滚标识。这个回滚标识在这里就会派上用场了,主要的应用场景如下。

某个事务是另一个事务的嵌人事务,但是,这些事务又不在Spring的管理范围内,或者无法设置保存点,那么Spring会通过设置回滚标识的方式来禁止提交。首先当某个嵌人事务发生回滚的时候会设置回滚标识,而等到外部事务提交时,一旦判断出当前事务流被设置了回滚标识,则由外部事务来统一进行整体事 务的回滚。

所以,当事务没有被异常捕获的时候也并不意味着一定会执行提交的过程。

对于内嵌事务,在Spring中正常的处理方式是将内嵌事务开始之前设置保存点,一旦内嵌事务出现异常便根据保存点信息进行回滚,但是如果没有出现异常,内嵌事务并不会单独提交,而是根据事务流由最外层事务负责提交,所以如果当前存在保存点信息便不是最外层事务,不做保存操作,对于是否是新事务的判断也是基于此考虑。

 

1、当事务状态中有保存点信息的不会去提交事务

2、当事务非新事务的时候也不会去执行提交事务操作

3、自定义触发器的调用,包括在提交前、完成提交后的调用,当然完成提交包括正常提交与提交过程中出现异常,自定义的触发器会根据这些信息作进一步处理,而对于触发器的注册,常见是在回调过程中通过TransactionSynchronizationManager类中的静态方法直接注册:

public static void registerSynchronization (TransactionSynchronization synchronization)

4、当之前已经保存的事务信息中有保存点信息的时候,内嵌事务并不会单独提交释放保存点信息,而是根据事务流由最外层事务负责提交。获取全局仅回滚标识

5、当之前已经保存的事务信息中的事务为新事务,那么直接回滚提交用于单独事务的处理,实际提交操作是由子类doCommit函数执行。获取全局仅回滚标识

6、不属于以上两种情况,获取全局仅回滚标识

7、根据获取全局仅回滚标识判断是否抛出异常

8、对于提交逻辑执行结束后,无论提交是否成功,都必须要做的事情就是事务结束后的收尾工作。

设置状态是对事务信息作完成标识以避免重复调用

调用子类方法doCleanupAfterCompletion

如果在事务执行前有事务挂起,那么当前事务执行结束后需要将挂起事务恢复

 

4.2 提交事务 commit

public final void commit(TransactionStatus status) throws TransactionException {

 if (status.isCompleted()) {

  throw new IllegalTransactionStateException(

    "Transaction is already completed - do not call commit or rollback more than once per transaction");

 }

 

 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;

 if (defStatus.isLocalRollbackOnly()) {

  if (defStatus.isDebug()) {

   logger.debug("Transactional code has requested rollback");

  }

  // 传送门5.3

  processRollback(defStatus, false);

  return;

 }

 

 // 5.3 回滚时可能会设置会滚标识

 if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {

  if (defStatus.isDebug()) {

   logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");

  }

  // 传送门5.3

  processRollback(defStatus, true);

  return;

 }

 

 processCommit(defStatus);

}

 

4.3 处理提交操作 processCommit

private void processCommit(DefaultTransactionStatus status) throws TransactionException {

 try {

  boolean beforeCompletionInvoked = false;

 

  try {

   boolean unexpectedRollback = false;

   // 为提交做准备,要在 {@code beforeCommit}同步回调发生之前执行。留给子类实现

   prepareForCommit(status);

   triggerBeforeCommit(status);

   triggerBeforeCompletion(status);

   beforeCompletionInvoked = true;

 

   if (status.hasSavepoint()) {

    if (status.isDebug()) {

     logger.debug("Releasing transaction savepoint");

    }

    // 获取回滚标识

    unexpectedRollback = status.isGlobalRollbackOnly();

    status.releaseHeldSavepoint();

   }

   else if (status.isNewTransaction()) {

    if (status.isDebug()) {

     logger.debug("Initiating transaction commit");

    }

    // 获取回滚标识

    unexpectedRollback = status.isGlobalRollbackOnly();

    // 留给子类实现

    doCommit(status);

   }

   else if (isFailEarlyOnGlobalRollbackOnly()) {

    // 获取回滚标识

    unexpectedRollback = status.isGlobalRollbackOnly();

   }

 

   // 如果我们有一个仅全局回滚标记,则抛出UnexpectedRollbackException,但仍未从提交中获得相应异常

   if (unexpectedRollback) {

    throw new UnexpectedRollbackException(

      "Transaction silently rolled back because it has been marked as rollback-only");

   }

  }

  catch (UnexpectedRollbackException ex) {

   // can only be caused by doCommit

   triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

   throw ex;

  }

  catch (TransactionException ex) {

   // can only be caused by doCommit

   if (isRollbackOnCommitFailure()) {

    doRollbackOnCommitException(status, ex);

   }

   else {

    triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);

   }

   throw ex;

  }

  catch (RuntimeException | Error ex) {

   if (!beforeCompletionInvoked) {

    triggerBeforeCompletion(status);

   }

   doRollbackOnCommitException(status, ex);

   throw ex;

  }

 

  // Trigger afterCommit callbacks, with an exception thrown there

  // propagated to callers but the transaction still considered as committed.

  try {

   triggerAfterCommit(status);

  }

  finally {

   triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);

  }

 }

 finally {

  cleanupAfterCompletion(status);

 }

}

 

4.4 提交前触发的操作 triggerBeforeCommit

protected final void triggerBeforeCommit(DefaultTransactionStatus status) {

 if (status.isNewSynchronization()) {

  if (status.isDebug()) {

   logger.trace("Triggering beforeCommit synchronization");

  }

  TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly());

 }

}

 

4.5 提交后触发的操作 triggerAfterCommit

private void triggerAfterCommit(DefaultTransactionStatus status) {

 if (status.isNewSynchronization()) {

  if (status.isDebug()) {

   logger.trace("Triggering afterCommit synchronization");

  }

  TransactionSynchronizationUtils.triggerAfterCommit();

 }

}

 

4.6 提交失败回滚操作 doRollbackOnCommitException

private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) throws TransactionException {

 try {

  if (status.isNewTransaction()) {

   if (status.isDebug()) {

    logger.debug("Initiating transaction rollback after commit exception", ex);

   }

   // 留给子类实现

   doRollback(status);

  }

  else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) {

   if (status.isDebug()) {

    logger.debug("Marking existing transaction as rollback-only after commit exception", ex);

   }

    // 留给子类实现,设置回滚标识

   doSetRollbackOnly(status);

  }

 }

 catch (RuntimeException | Error rbex) {

  logger.error("Commit exception overridden by rollback exception", ex);

  triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);

  throw rbex;

 }

 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

}

 

五、回滚事务 rollback

5.1 回滚处理流程


1、首先是自定义触发器的调用,包括在回滚前、完成回滚后的调用,当然完成回滚包括正常回滚与回滚过程中出现异常,自定义的触发器会根据这些信息作进一步处理,而对于触发器的注册,常见是在回调过程中通过TransactionSynchronizationManager类中的静态方法直接注册:

public static void registerSynchronization (TransactionSynchronization synchronization)

2、当之前已经保存的事务信息中有保存点信息的时候,使用保存点信息进行回滚。常用于嵌入式事务,对于嵌入式的事务的处理,内嵌的事务异常并不会引起外部事务的回滚。

3、当之前已经保存的事务信息中的事务为新事务,那么直接回滚。常用于单独事务的处理。对于没有保存点的回滚,Spring 同样是使用底层数据库连接提供的API来操作的。实际回滚操作是由子类doRollback函数执行。

4、当前事务信息中表明是存在事务的,又不属于以上两种情况,多数用于JTA,只做回滚标识,等到提交的时候统一不提交。

5、对于回滚逻辑执行结束后,无论回滚是否成功,都必须要做的事情就是事务结束后的收尾工作。

设置状态是对事务信息作完成标识以避免重复调用

调用子类方法doCleanupAfterCompletion

如果在事务执行前有事务挂起,那么当前事务执行结束后需要将挂起事务恢复

 

 

5.2 回滚事务 rollback

public final void rollback(TransactionStatus status) throws TransactionException {

 if (status.isCompleted()) {

  throw new IllegalTransactionStateException(

    "Transaction is already completed - do not call commit or rollback more than once per transaction");

 }

 

 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;

 processRollback(defStatus, false);

}

 

5.3 处理回滚操作 processRollback

private void processRollback(DefaultTransactionStatus status, boolean unexpected) {

 try {

  boolean unexpectedRollback = unexpected;

 

  try {

   triggerBeforeCompletion(status);

 

   if (status.hasSavepoint()) {

    if (status.isDebug()) {

     logger.debug("Rolling back transaction to savepoint");

    }

    status.rollbackToHeldSavepoint();

   }

   else if (status.isNewTransaction()) {

    if (status.isDebug()) {

     logger.debug("Initiating transaction rollback");

    }

    // 留给子类实现

    doRollback(status);

   }

   else {

    // Participating in larger transaction

    if (status.hasTransaction()) {

     if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {

      if (status.isDebug()) {

       logger.debug("Participating transaction failed - marking existing transaction as rollback-only");

      }

      // 设置事务回滚:当前事务参与已有事务。如果当前事务不是独立的事务,那么只能标记状态,等到事务链执行完毕后统一回滚

      doSetRollbackOnly(status);

     }

     else {

      if (status.isDebug()) {

       logger.debug("Participating transaction failed - letting transaction originator decide on rollback");

      }

     }

    }

    else {

     logger.debug("Should roll back transaction but cannot - no transaction available");

    }

 

    // 返回在事务全局标记为“仅回滚”的情况下是否提前失败。

    if (!isFailEarlyOnGlobalRollbackOnly()) {

     unexpectedRollback = false;

    }

   }

  }

  catch (RuntimeException | Error ex) {

   triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);

   throw ex;

  }

 

  triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

 

  // 如果我们有一个仅全局回滚的标记,则引发UnexpectedRollbackException

  if (unexpectedRollback) {

   throw new UnexpectedRollbackException(

     "Transaction rolled back because it has been marked as rollback-only");

  }

 }

 finally {

  // 清空记录的资源并将挂起的资源恢复

  cleanupAfterCompletion(status);

 }

}

 

5.4 事务完成前触发的操作 triggerBeforeCompletion

protected final void triggerBeforeCompletion(DefaultTransactionStatus status) {

 if (status.isNewSynchronization()) {

  if (status.isDebug()) {

   logger.trace("Triggering beforeCompletion synchronization");

  }

 

   // 在当前所有已注册的事务同步上触发{@code beforeCompletion}回调。TransactionSynchronizationManager.getSynchronizations()

  TransactionSynchronizationUtils.triggerBeforeCompletion();

 }

}

 

5.5 事务完成后触发的操作 triggerAfterCompletion

private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {

 if (status.isNewSynchronization()) {

  List synchronizations = TransactionSynchronizationManager.getSynchronizations();

  // 清空事务同步

  TransactionSynchronizationManager.clearSynchronization();

  if (!status.hasTransaction() || status.isNewTransaction()) {

   if (status.isDebug()) {

    logger.trace("Triggering afterCompletion synchronization");

   }

   // 当前范围内没有事务或新事务-> 立即调用afterCompletion回调

   invokeAfterCompletion(synchronizations, completionStatus);

  }

  else if (!synchronizations.isEmpty()) {

   // Existing transaction that we participate in, controlled outside

   // of the scope of this Spring transaction manager -> try to register

   // an afterCompletion callback with the existing (JTA) transaction.

   registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);

  }

 }

}

 

// 子类可以重写

protected void registerAfterCompletionWithExistingTransaction(

  Object transaction, List synchronizations) throws TransactionException {

 logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +

   "processing Spring after-completion callbacks immediately, with outcome status 'unknown'");

 invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);

}

 

protected final void invokeAfterCompletion(List synchronizations, int completionStatus) {

 TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus);

}

 

六、事务完成后清理资源 cleanupAfterCompletion

6.1 事务完成后清理资源 cleanupAfterCompletion

// 清空记录的资源并将挂起的资源恢复

private void cleanupAfterCompletion(DefaultTransactionStatus status) {

 status.setCompleted();

 if (status.isNewSynchronization()) {

  TransactionSynchronizationManager.clear();

 }

 if (status.isNewTransaction()) {

  // 留给子类实现

  doCleanupAfterCompletion(status.getTransaction());

 }

 if (status.getSuspendedResources() != null) {

  if (status.isDebug()) {

   logger.debug("Resuming suspended transaction after completion of inner transaction");

  }

  Object transaction = (status.hasTransaction() ? status.getTransaction() : null);

  // 恢复挂起的事务:传送门3.10

  resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());

 }

}

 

七、DataSourceTransactionManager

7.1 获取事务

7.1.1 获取当前线程的事务 doGetTransaction

protected Object doGetTransaction() {

 // DataSourceTransactionObject实现了SavepointManager接口

 DataSourceTransactionObject txObject = new DataSourceTransactionObject();

 txObject.setSavepointAllowed(isNestedTransactionAllowed());

 // 获取当前线程持有者

 ConnectionHolder conHolder =

   (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());

 txObject.setConnectionHolder(conHolder, false);

 return txObject;

}

 

7.1.2 当前线程事务是否存在 isExistingTransaction

protected boolean isExistingTransaction(Object transaction) {

 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

 return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());

}

 

7.1.3 开启新事务初始化工作 doBegin

  1. 尝试获取连接

当然并不是每次都会获取新的连接,如果当前线程中的connectionHolder不存在或者存在且事务同步标识设置为true需要重新获取连接。设置事务同步标识为true。

  1. 设置隔离级别以及只读标识。

Spring中确实是针对只读操作做了一些处理,但是核心的实现是设置connection 上的readOnly属性。同样,对于隔离级别的控制也是交由connection 去控制的。

  1. 更改默认的提交设置。

如果事务属性是自动提交,那么需要改变这种设置,而将提交操作委托给Spring来处理。

  1. 设置标志位,标识当前连接已经被事务激活。
  2. 设置过期时间。
  3. 将新创建的connectionHolder绑定到当前线程。

 

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");

   }

   txObject.setConnectionHolder(new ConnectionHolder(newCon), true);

  }

 

  // 资源是否和事务同步,如果同步资源则重复使用,见DataSourceUtils.doGetConnection

  txObject.getConnectionHolder().setSynchronizedWithTransaction(true);

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

 

  // 获取当前线程事务隔离级别并保存,新事务完成后需要恢复之前的事务隔离级别

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

  txObject.setPreviousIsolationLevel(previousIsolationLevel);

 

  // 如有必要,请切换为手动提交。在某些JDBC驱动程序中,这是非常昂贵的,因此我们不想不必要地进行操作(例如,如果我们已经明确配置连接池以进行设置)。保存数据库连接自动提交信息,并设置为手动提交

  if (con.getAutoCommit()) {

   txObject.setMustRestoreAutoCommit(true);

   if (logger.isDebugEnabled()) {

    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");

   }

   con.setAutoCommit(false);

  }

 

  // 如果{@link #setEnforceReadOnly“ enforceReadOnly”}标志设置为{@code true},并且事务定义指示只读事务,则默认实现将执行“ SET TRANSACTION READ ONLY”语句。

  prepareTransactionalConnection(con, definition);

  // 设置判断当前线程是否存在事务的依据。传送门:7.1.2 检测当前线程事务是否存在时会用到

  txObject.getConnectionHolder().setTransactionActive(true);

 

  int timeout = determineTimeout(definition);

  if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {

   txObject.getConnectionHolder().setTimeoutInSeconds(timeout);

  }

 

  // 如果是新的连接,将连接绑定到当前线程上

  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);

 }

}

 

7.1.3.1 准备事务连接 prepareTransactionalConnection

// 事务开始后立即准备事务{@code Connection}。 如果{@link #setEnforceReadOnly“ enforceReadOnly”}标志设置为{@code true},并且事务定义指示只读事务,则默认实现将执行“ SET TRANSACTION READ ONLY”语句。Oracle,MySQL和Postgres可以理解“ SET TRANSACTION READ ON”(只读),并且也可以与其他数据库一起使用。如果您想采用这种处理方法,请相应地重写此方法。

protected void prepareTransactionalConnection(Connection con, TransactionDefinition definition)

  throws SQLException {

 

 if (isEnforceReadOnly() && definition.isReadOnly()) {

  Statement stmt = con.createStatement();

  try {

   stmt.executeUpdate("SET TRANSACTION READ ONLY");

  }

  finally {

   stmt.close();

  }

 }

}

 

7.2 挂起事务 doSuspend

// 从当前线程中取消给定数据源绑定的数据库连接

protected Object doSuspend(Object transaction) {

 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

 txObject.setConnectionHolder(null);

 return TransactionSynchronizationManager.unbindResource(obtainDataSource());

}

 

7.3 恢复事务 doResume

 

// 当前线程中数据库连接绑定到给定数据源。

protected void doResume(@Nullable Object transaction, Object suspendedResources) {

 TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);

}

 

7.4 提交事务 doCommit

protected void doCommit(DefaultTransactionStatus status) {

 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();

 Connection con = txObject.getConnectionHolder().getConnection();

 if (status.isDebug()) {

  logger.debug("Committing JDBC transaction on Connection [" + con + "]");

 }

 try {

  con.commit();

 }

 catch (SQLException ex) {

  throw new TransactionSystemException("Could not commit JDBC transaction", ex);

 }

}

 

7.5 回滚事务 doRollback

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);

 }

}

 

7.6 事务完成后清理资源 doCleanupAfterCompletion

protected void doCleanupAfterCompletion(Object transaction) {

 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

 

 // 如果是新的连接,从当前线程中取消给定数据源绑定的数据库连接

 if (txObject.isNewConnectionHolder()) {

  TransactionSynchronizationManager.unbindResource(obtainDataSource());

 }

 

 // 重置数据库连接:自动提交、事物隔离级别

 Connection con = txObject.getConnectionHolder().getConnection();

 try {

  if (txObject.isMustRestoreAutoCommit()) {

   con.setAutoCommit(true);

  }

  DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());

 }

 catch (Throwable ex) {

  logger.debug("Could not reset JDBC Connection after transaction", ex);

 }

 

 // 如果是新的连接,没有外部管理(即未绑定到线程),则关闭从给定的DataSource获得的给定的Connection

 if (txObject.isNewConnectionHolder()) {

  if (logger.isDebugEnabled()) {

   logger.debug("Releasing JDBC Connection [" + con + "] after transaction");

  }

  DataSourceUtils.releaseConnection(con, this.dataSource);

 }

 

 txObject.getConnectionHolder().clear();

}

 

7.7 设置事务仅回滚 doSetRollbackOnly

// 设置给定的事务仅回滚,仅当当前事务参与现有事务时才调用回滚

protected void doSetRollbackOnly(DefaultTransactionStatus status) {

 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();

 if (status.isDebug()) {

  logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() +

    "] rollback-only");

 }

 txObject.setRollbackOnly();

}

 

7.8 事务对象 DataSourceTransactionObject

private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport {

 private boolean newConnectionHolder;

 

 private boolean mustRestoreAutoCommit;

 

 public void setConnectionHolder(@Nullable ConnectionHolder connectionHolder, boolean newConnectionHolder) {

  super.setConnectionHolder(connectionHolder);

  this.newConnectionHolder = newConnectionHolder;

 }

 

 public boolean isNewConnectionHolder() {

  return this.newConnectionHolder;

 }

 

 public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) {

  this.mustRestoreAutoCommit = mustRestoreAutoCommit;

 }

 

 public boolean isMustRestoreAutoCommit() {

  return this.mustRestoreAutoCommit;

 }

 

 public void setRollbackOnly() {

  getConnectionHolder().setRollbackOnly();

 }

 

 @Override

 public boolean isRollbackOnly() {

  return getConnectionHolder().isRollbackOnly();

 }

 

 @Override

 public void flush() {

  if (TransactionSynchronizationManager.isSynchronizationActive()) {

   TransactionSynchronizationUtils.triggerFlush();

  }

 }

}

你可能感兴趣的:(Spring5.x)