// org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction@NullableprotectedObjectinvokeWithinTransaction(Method method,@NullableClass<?> targetClass,finalInvocationCallback invocation)throwsThrowable{// If the transaction attribute is null, the method is non-transactional.TransactionAttributeSource tas =getTransactionAttributeSource();finalTransactionAttribute txAttr =(tas !=null? tas.getTransactionAttribute(method, targetClass):null);finalTransactionManager tm =determineTransactionManager(txAttr);if(this.reactiveAdapterRegistry !=null&& tm instanceofReactiveTransactionManager){ReactiveTransactionSupport txSupport =this.transactionSupportCache.computeIfAbsent(method, key ->{if(KotlinDetector.isKotlinType(method.getDeclaringClass())&&KotlinDelegate.isSuspend(method)){thrownewTransactionUsageException("Unsupported annotated transaction on suspending function detected: "+ method +". Use TransactionalOperator.transactional extensions instead.");}ReactiveAdapter adapter =this.reactiveAdapterRegistry.getAdapter(method.getReturnType());if(adapter ==null){thrownewIllegalStateException("Cannot apply reactive transaction to non-reactive return type: "+
method.getReturnType());}returnnewReactiveTransactionSupport(adapter);});return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr,(ReactiveTransactionManager) tm);}PlatformTransactionManager ptm =asPlatformTransactionManager(tm);finalString joinpointIdentification =methodIdentification(method, targetClass, txAttr);if(txAttr ==null||!(ptm instanceofCallbackPreferringPlatformTransactionManager)){// Standard transaction demarcation with getTransaction and commit/rollback calls.TransactionInfo txInfo =createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);Object retVal;try{// 执行入参中的回调函数,即参与到拦截器链的演进逻辑中// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();}catch(Throwable ex){// step into ...// target invocation exceptioncompleteTransactionAfterThrowing(txInfo, ex);throw ex;}finally{// step into ..// 把当前线程绑定的事务改成之前的事务(比如:将子事务切换到父事务)cleanupTransactionInfo(txInfo);}if(retVal !=null&& vavrPresent &&VavrDelegate.isVavrTry(retVal)){// Set rollback-only in case of Vavr failure matching our rollback rules...TransactionStatus status = txInfo.getTransactionStatus();if(status !=null&& txAttr !=null){
retVal =VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}}// step into ...commitTransactionAfterReturning(txInfo);return retVal;}else{Object result;finalThrowableHolder throwableHolder =newThrowableHolder();// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.try{
result =((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status ->{TransactionInfo txInfo =prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);try{Object retVal = invocation.proceedWithInvocation();if(retVal !=null&& vavrPresent &&VavrDelegate.isVavrTry(retVal)){// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal =VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}return retVal;}catch(Throwable ex){if(txAttr.rollbackOn(ex)){// A RuntimeException: will lead to a rollback.if(ex instanceofRuntimeException){throw(RuntimeException) ex;}else{thrownewThrowableHolderException(ex);}}else{// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;returnnull;}}finally{cleanupTransactionInfo(txInfo);}});}catch(ThrowableHolderException ex){throw ex.getCause();}catch(TransactionSystemException ex2){if(throwableHolder.throwable !=null){
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);}throw ex2;}catch(Throwable ex2){if(throwableHolder.throwable !=null){
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);}throw ex2;}// Check result state: It might indicate a Throwable to rethrow.if(throwableHolder.throwable !=null){throw throwableHolder.throwable;}return result;}}
// org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturningprotectedvoidcommitTransactionAfterReturning(@NullableTransactionInfo txInfo){if(txInfo !=null&& txInfo.getTransactionStatus()!=null){if(logger.isTraceEnabled()){
logger.trace("Completing transaction for ["+ txInfo.getJoinpointIdentification()+"]");}// step into ...
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}}// org.springframework.transaction.support.AbstractPlatformTransactionManager#commit@Overridepublicfinalvoidcommit(TransactionStatus status)throwsTransactionException{if(status.isCompleted()){thrownewIllegalTransactionStateException("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");}processRollback(defStatus,false);return;}// shouldCommitOnGlobalRollbackOnly() 一般返回false,JTA返回true// isGlobalRollbackOnly(),对于JDBC连接来说,看是否需要回滚,即rollBackOnlyif(!shouldCommitOnGlobalRollbackOnly()&& defStatus.isGlobalRollbackOnly()){if(defStatus.isDebug()){
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");}processRollback(defStatus,true);return;}// step into ...// 不需要回滚走这里processCommit(defStatus);}// org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommitprivatevoidprocessCommit(DefaultTransactionStatus status)throwsTransactionException{try{boolean beforeCompletionInvoked =false;try{boolean unexpectedRollback =false;prepareForCommit(status);// 对只读事务的处理triggerBeforeCommit(status);// 回调Synchronization对应的方法,具体内容前面已经提及triggerBeforeCompletion(status);
beforeCompletionInvoked =true;// NESTED走这里if(status.hasSavepoint()){if(status.isDebug()){
logger.debug("Releasing transaction savepoint");}// 这跟前面一样的,rollBackOnly=false(不需要回滚时)
unexpectedRollback = status.isGlobalRollbackOnly();// step into ...// 这个也是雷同的
status.releaseHeldSavepoint();}elseif(status.isNewTransaction()){if(status.isDebug()){
logger.debug("Initiating transaction commit");}
unexpectedRollback = status.isGlobalRollbackOnly();// step into ...// 看看外层事务怎么提交doCommit(status);}elseif(isFailEarlyOnGlobalRollbackOnly()){
unexpectedRollback = status.isGlobalRollbackOnly();}// Throw UnexpectedRollbackException if we have a global rollback-only// marker but still didn't get a corresponding exception from commit.if(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction silently rolled back because it has been marked as rollback-only");}}catch(UnexpectedRollbackException ex){// can only be caused by doCommittriggerAfterCompletion(status,TransactionSynchronization.STATUS_ROLLED_BACK);throw ex;}catch(TransactionException ex){// can only be caused by doCommitif(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{// step into ...// 回调绑定到当前线程的TransactionSynchronizationtriggerAfterCommit(status);}finally{// step into ...triggerAfterCompletion(status,TransactionSynchronization.STATUS_COMMITTED);}}finally{cleanupAfterCompletion(status);}}
// org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCompletionprivatevoidtriggerAfterCompletion(DefaultTransactionStatus status,int completionStatus){if(status.isNewSynchronization()){List<TransactionSynchronization> synchronizations =TransactionSynchronizationManager.getSynchronizations();TransactionSynchronizationManager.clearSynchronization();if(!status.hasTransaction()|| status.isNewTransaction()){if(status.isDebug()){
logger.trace("Triggering afterCompletion synchronization");}// No transaction or new transaction for the current scope ->// invoke the afterCompletion callbacks immediatelyinvokeAfterCompletion(synchronizations, completionStatus);}elseif(!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);}}// step out ...}
// org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfoprotectedvoidcleanupTransactionInfo(@NullableTransactionInfo txInfo){if(txInfo !=null){// step into ...
txInfo.restoreThreadLocalStatus();}}// org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#restoreThreadLocalStatusprivatevoidrestoreThreadLocalStatus(){// step out ...// Use stack to restore old transaction TransactionInfo.// Will be null if none was set.
transactionInfoHolder.set(this.oldTransactionInfo);}