Spring事务处理 - 事务处理的过程

   Spring的声明式事务处理的即开即用特性为用户提供了很大的方便,在使用Spring时,我们绝大多数情况下还是使用其声明式事务处理。声明式事务处理涉及Spring框架对事务处理的统一管理,以及对并发事务和事务属性的处理,是一个比较复杂的过程,下面了解一下Spring框架声明式事务处理功能的具体实现。

一、事务的创建

前一篇文章讲到对Spring事务拦截器TransactionInterceptor回调方法invoke的源码分析中,我们了解到在进行事务处理前,首先根据是否是CallbackPreferringPlatformTransactionManager类型的事务处理器分别通过下面两个方法创建事务信息对象:

[html]  view plain  copy
  1. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);     
  2. TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);     

二、事务的挂起

如果当前线程存在事务,但事务传播特性又要求开启新事务时,需要将已有的事务进行挂起,事务的挂起涉及线程与事务信息的保存,实现源码如下:

[html]  view plain  copy
  1. protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {  
  2.         //如果事务是激活的,且当前线程事务同步机制也是激活状态  
  3.         if (TransactionSynchronizationManager.isSynchronizationActive()) {  
  4.             //挂起当前线程中所有同步的事务  
  5.             List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();  
  6.             try {  
  7.                 Object suspendedResources = null;  
  8.                 //把挂起事务的操作交由具体的事务处理器处理  
  9.                 if (transaction != null) {  
  10.                     suspendedResources = doSuspend(transaction);  
  11.                 }  
  12.             //在线程中保存与事务处理有关的信息,并将线程里有关的线程局部变量重置  
  13.                 String name = TransactionSynchronizationManager.getCurrentTransactionName();  
  14. //重置当前线程中事务相关的线程局部变量  
  15. TransactionSynchronizationManager.setCurrentTransactionName(null);  
  16.                 boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();  
  17.     TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);  
  18.                 Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();  
  19.     TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);  
  20.                 boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();  
  21.     TransactionSynchronizationManager.setActualTransactionActive(false);  
  22.                 //将当前线程中事务相关信息保存  
  23.                 return new SuspendedResourcesHolder(  
  24.                         suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);  
  25.             }  
  26.             //对事务挂起操作中产生异常和错误的处理  
  27.             catch (RuntimeException ex) {  
  28.                 doResumeSynchronization(suspendedSynchronizations);  
  29.                 throw ex;  
  30.             }  
  31.             catch (Error err) {  
  32.                 doResumeSynchronization(suspendedSynchronizations);  
  33.                 throw err;  
  34.             }  
  35.         }  
  36.         //如果事务是激活的,但是事务同步机制不是激活的,则只需要保存事务状态,不  
  37. //需要重置事务相关的线程局部变量  
  38.         else if (transaction != null) {  
  39.             Object suspendedResources = doSuspend(transaction);  
  40.             return new SuspendedResourcesHolder(suspendedResources);  
  41.         }  
  42.         //事务和事务同步机制都不是激活的,则不要想处理  
  43.         else {  
  44.             return null;  
  45.         }  
  46.     }  

三、事务的提交

当事务方法处理成功之后,需要将当前事务提交,将更改同步到数据库中,事务提交的实现源码如下:

[html]  view plain  copy
  1. public final void commit(TransactionStatus status) throws TransactionException {  
  2.         //如果事务的执行状态已经结束,则抛出异常  
  3.         if (status.isCompleted()) {  
  4.             throw new IllegalTransactionStateException(  
  5.                     "Transaction is already completed - do not call commit or rollback more than once per transaction");  
  6.         }  
  7.         DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;  
  8.         //如果事务执行状态时回滚  
  9.         if (defStatus.isLocalRollbackOnly()) {  
  10.             if (defStatus.isDebug()) {  
  11.                 logger.debug("Transactional code has requested rollback");  
  12.             }  
  13.             //处理事务回滚  
  14.             processRollback(defStatus);  
  15.             return;  
  16.         }  
  17.         //如果事务没有被标记为回滚时提交,且事务状态时全局回滚  
  18.         if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {  
  19.             if (defStatus.isDebug()) {  
  20.                 logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");  
  21.             }  
  22.             //回滚处理  
  23.             processRollback(defStatus);  
  24.             //如果事务状态时新事务,或者在全局回滚时失败  
  25.             if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {  
  26.                 throw new UnexpectedRollbackException(  
  27.                         "Transaction rolled back because it has been marked as rollback-only");  
  28.             }  
  29.             return;  
  30.         }  
  31.         //处理提交  
  32.         processCommit(defStatus);  
  33.     }  
  34.     //提交处理操作  
  35.     private void processCommit(DefaultTransactionStatus status) throws TransactionException {  
  36.         try {  
  37.             boolean beforeCompletionInvoked = false;  
  38.             try {  
  39.                 //事务提交的准备工作,有具体的事务处理器完成  
  40.                 prepareForCommit(status);  
  41.                 triggerBeforeCommit(status);  
  42.                 triggerBeforeCompletion(status);  
  43.                 beforeCompletionInvoked = true;  
  44.                 boolean globalRollbackOnly = false;  
  45.                 //如果事务状态是新事务,或者全局回滚失败  
  46.                 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {  
  47.                     //设置事务全局回滚  
  48.                     globalRollbackOnly = status.isGlobalRollbackOnly();  
  49.                 }  
  50.                 //嵌套事务处理  
  51.                 if (status.hasSavepoint()) {  
  52.                     if (status.isDebug()) {  
  53.                         logger.debug("Releasing transaction savepoint");  
  54.                     }  
  55.                     //释放挂起事务保存点  
  56.                     status.releaseHeldSavepoint();  
  57.                 }  
  58.                 //如果当前事务是新事务  
  59.                 else if (status.isNewTransaction()) {  
  60.                     if (status.isDebug()) {  
  61.                         logger.debug("Initiating transaction commit");  
  62.                     }  
  63.                     //调用具体事务处理器提交事务  
  64.                     doCommit(status);  
  65.                 }  
  66.                 //如果事务被标记为全局回滚  
  67.                 if (globalRollbackOnly) {  
  68.                     throw new UnexpectedRollbackException(  
  69.                             "Transaction silently rolled back because it has been marked as rollback-only");  
  70.                 }  
  71.             }  
  72.             //提交过程中产生未预期的回滚异常,则回滚处理  
  73.             catch (UnexpectedRollbackException ex) {  
  74.                 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);  
  75.                 throw ex;  
  76.             }  
  77.             //对提交过程中产生的事务异常处理  
  78.             catch (TransactionException ex) {  
  79.                 //如果回滚失败,则进行回滚异常处理  
  80.                 if (isRollbackOnCommitFailure()) {  
  81.                     doRollbackOnCommitException(status, ex);  
  82.                 }  
  83.                 else {  
  84.                     triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);  
  85.                 }  
  86.                 throw ex;  
  87.             }  
  88.             //对提交过程中产生的异常处理  
  89.             catch (RuntimeException ex) {  
  90.                 //如果不是在完成前调用的  
  91.                 if (!beforeCompletionInvoked) {  
  92.                     //触发完成前的回调方法  
  93.                     triggerBeforeCompletion(status);  
  94.                 }  
  95.                 //进行回滚异常处理  
  96.                 doRollbackOnCommitException(status, ex);  
  97.                 throw ex;  
  98.             }  
  99. //对提交过程中产生的错误处理  
  100.             catch (Error err) {  
  101.                 if (!beforeCompletionInvoked) {  
  102.                     triggerBeforeCompletion(status);  
  103.                 }  
  104.                 doRollbackOnCommitException(status, err);  
  105.                 throw err;  
  106.             }  
  107.             //触发提交之后的回调操作  
  108.             try {  
  109.                 triggerAfterCommit(status);  
  110.             }  
  111.             finally {  
  112.                 triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);  
  113.             }  
  114.         }  
  115.         //提交完成之后清除事务相关状态  
  116.         finally {  
  117.             cleanupAfterCompletion(status);  
  118.         }  
  119.     }  

四、事务的回滚

当在事务处理过程中产生异常,或者提交失败时,往往需要对数据库中已有的更改做回滚操作,即恢复到操作之前的状态,回滚的实现代码如下:

[html]  view plain  copy
  1. public final void rollback(TransactionStatus status) throws TransactionException {  
  2.         //如果事务状态已完成,则抛出异常  
  3.         if (status.isCompleted()) {  
  4.             throw new IllegalTransactionStateException(  
  5.                     "Transaction is already completed - do not call commit or rollback more than once per transaction");  
  6.         }  
  7.         DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;  
  8.         //处理回滚的操作  
  9.         processRollback(defStatus);  
  10.     }   
  11. //回滚操作  
  12. private void processRollback(DefaultTransactionStatus status) {  
  13.         try {  
  14.             try {  
  15.                 //触发完成前的回调操作  
  16.                 triggerBeforeCompletion(status);  
  17.                 //嵌套事务回滚处理  
  18.                 if (status.hasSavepoint()) {  
  19.                     if (status.isDebug()) {  
  20.                         logger.debug("Rolling back transaction to savepoint");  
  21.                     }  
  22.                     //回滚挂起在保存点的事务  
  23.                     status.rollbackToHeldSavepoint();  
  24.                 }  
  25.                 //当前事务中创建新事务的回滚操作  
  26.                 else if (status.isNewTransaction()) {  
  27.                     if (status.isDebug()) {  
  28.                         logger.debug("Initiating transaction rollback");  
  29.                     }  
  30.                     //回滚处理,由具体的事务处理器实现  
  31.                     doRollback(status);  
  32.                 }  
  33.                 //如果在当前事务中没有新建事务  
  34.                 else if (status.hasTransaction()) {  
  35.                     //如果当前事务状态为本地回滚,或全局回滚失败  
  36.                     if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {  
  37.                         if (status.isDebug()) {  
  38.                             logger.debug(  
  39.                                     "Participating transaction failed - marking existing transaction as rollback-only");  
  40.                         }  
  41.                         //设置当前事务状态为回滚  
  42.                         doSetRollbackOnly(status);  
  43.                     }  
  44.                     //当前事务状态没有设置为本地回滚,且没有产生全局回滚失败,则  
  45. //由线程中的前一个事务来处理回滚,这个步骤任何处理  
  46.                     else {  
  47.                         if (status.isDebug()) {  
  48.                             logger.debug(  
  49.                                     "Participating transaction failed - letting transaction originator decide on rollback");  
  50.                         }  
  51.                     }  
  52.                 }  
  53.                 //如果当前线程没有事务  
  54.                 else {  
  55.                     logger.debug("Should roll back transaction but cannot - no transaction available");  
  56.                 }  
  57.             }  
  58.             //对回滚操作过程中的运行时异常和错误的处理  
  59.             catch (RuntimeException ex) {  
  60.                 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);  
  61.                 throw ex;  
  62.             }  
  63.             catch (Error err) {  
  64.                 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);  
  65.                 throw err;  
  66.             }  
  67.             //回滚操作完成后,触发回滚之后回调操作  
  68.             triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);  
  69.         }  
  70.         //清除回滚之后事务状态信息  
  71.         finally {  
  72.             cleanupAfterCompletion(status);  
  73.         }  
  74.     }  

猜你喜欢

转载自blog.csdn.net/qq853632587/article/details/80485289