SpringTransactionFramework之TransactionManager分析commit和rollback方法。commit方法也在AbstractPlantformTransactionManager中定义。可以看到commit方法的参数是TransactionStatus,也是之前开启事务的getTransaction返回的对象。先判断事务状态,如果完成则抛出异常。publicfinalvoidcommit(TransactionStatusstatus)throwsTransactionException{if(status.isCompleted()){thrownewIllegalTransactionStateException("交易已经完成-每个交易不要多次调用提交或回滚");}然后判断当前事务是否设置为只回滚,如果是则调用processRollback方法回滚。否则,调用processCommit方法提交事务。DefaultTransactionStatusdefStatus=(DefaultTransactionStatus)状态;if(defStatus.isLocalRollbackOnly()){if(defStatus.isDebug()){logger.debug("事务代码已请求回滚");}processRollback(defStatus,false);返回;}if(!shouldCommitOnGlobalRollbackOnly()&&defStatus.isGlobalRollbackOnly()){if(defStatus.isDebug()){logger.debug("全局事务被标记为只回滚但事务代码请求提交");}processRollback(defStatus,真);返回;}processCommit(defStatus);processCommitprocessCommit方法仍然在AbstractPlantformTransactionManager中。处理实际提交。rollback-onlyflags已经被检查并应用了。Params:status–代表事务的对象Throws:TransactionException–在提交失败的情况下执行真正的提交,如果设置了回滚标志,可以看到回滚事务运行在processCommit之后,事务可能仍会回滚。调用prepareForCommit做pre-commit准备,调用triggerBeforeCommit/triggerBeforeCompletion触发pre-commit监听。尝试{booleanbeforeCompletionInvoked=false;尝试{布尔值unexpectedRollback=false;准备提交(状态);触发前提交(状态);triggerBeforeCompletion(状态);没有实施。所以这个方法可能留作扩展用。我们不会分析所有的提交前和提交后监听处理。个人觉得不是很重要,适用场景也很少。那么我们继续往下看,查看status中是否有保存点。如果是这样,释放保存点。这里需要留一个小问题。当传播机制设置为嵌套时,开启的事务会设置保存点,代码逻辑应该是来到这里,但是保存点只在这里释放,后面不调用commit,不应该这样做。暂时怀疑。if(status.hasSavepoint()){if(status.isDebug()){logger.debug("释放事务保存点");}unexpectedRollback=status.isGlobalRollbackOnly();status.releaseHeldSavepoint();说到真正的事务提交方法doCommit,注意status的isNewTransaction必须为true才可以提交事务。elseif(status.isNewTransaction()){if(status.isDebug()){logger.debug("初始化事务提交");}unexpectedRollback=status.isGlobalRollbackOnly();做提交(状态);}之后是事务commit处理,判断commit时如果出现异常,则回滚事务,然后就是commit后的监控过程,这里不再详细分析。doCommitcommit方法的最终提交真相在这里。我们已经知道他肯定是在DataSourceTransactionManager中实现的。至此,铺垫和准备工作已经完成,提交方法本身也很简单。通过TransactionStatus获取事务对象transaction,通过其持有的ConnectionHolder获取数据库连接Connection,然后,就是Connection的commit方法。protectedvoiddoCommit(DefaultTransactionStatusstatus){DataSourceTransactionObjecttxObject=(DataSourceTransactionObject)status.getTransaction();连接con=txObject.getConnectionHolder().getConnection();if(status.isDebug()){logger.debug("在连接上提交JDBC事务["+con+"]");}尝试{con.commit();}catch(SQLExceptionex){throwtranslateException("JDBCcommit",ex);前面的getTransaction和commit方法在调用doCommit方法之前的一堆准备操作相当于弯弓搭箭,最后con.commit终于射到数据库了。最复杂的事务提交(其实就是数据的打开,事务下的SQL语句执行等)都dump到数据库中去处理。commit方法分析。rollback其实分析commit方法后,rollback方法是没有什么秘密的。rollback方法也在AbstractPlatformTranactionManager中,结构和commit几乎一样,不同的是在processRollback如果事务有保存点:if(status.hasSavepoint()){if(status.isDebug()){logger.debug("回滚事务到保存点");}status.rollbackToHeldSavepoint();调用TransactionStatus的rollbackToHeldSavepoint回滚到保存点。其他代码结构和commit差不多,调用doRollback方法,然后就是回滚的后处理。DataSourcePlantformTransactionManager中也实现了doRollback方法,用于获取数据库连接,调用数据库连接的回滚:protectedvoiddoRollback(DefaultTransactionStatusstatus){连接con=txObject.getConnectionHolder().getConnection();if(status.isDebug()){logger.debug("回滚连接上的JDBC事务["+con+"]");}尝试{con.rollback();}catch(SQLExceptionex){throwtranslateException("JDBC回滚",ex);}}OK,TransactionMnaager的三大方法:启动事务、提交事务、回滚事务解析完毕。后来对Spring事务管理的相关支持包括事务使能机制(@EnableTransactionManagement)和事务控制(@Transactional),可以看作是Spring事务框架的具体应用。有机会再做详细分析。上一篇Spring事务框架之TransactionManager(三)下一篇启用Spring事务管理@EnableTransactionManagement(一)
