// public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor// org.springframework.transaction.interceptor.TransactionInterceptor#invoke@Override@NullablepublicObjectinvoke(MethodInvocation invocation)throwsThrowable{// 获取被代理的类// 因为TransactionAttribute是间接的跟targetClass绑定的// Work out the target class: may be {@code null}.// The TransactionAttributeSource should be passed the target class// as well as the method, which may be from an interface.Class<?> targetClass =(invocation.getThis()!=null?AopUtils.getTargetClass(invocation.getThis()):null);// step into ...// Adapt to TransactionAspectSupport's invokeWithinTransaction...returninvokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);}// 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;}}
2. completeTransactionAfterThrowing:回滚
// org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowingprotectedvoidcompleteTransactionAfterThrowing(@NullableTransactionInfo txInfo,Throwable ex){if(txInfo !=null&& txInfo.getTransactionStatus()!=null){if(logger.isTraceEnabled()){
logger.trace("Completing transaction for ["+ txInfo.getJoinpointIdentification()+"] after exception: "+ ex);}// step into ...// 回滚还是直接提交if(txInfo.transactionAttribute !=null&& txInfo.transactionAttribute.rollbackOn(ex)){try{// step into ...
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch(TransactionSystemException ex2){
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);throw ex2;}catch(RuntimeException|Error ex2){
logger.error("Application exception overridden by rollback exception", ex);throw ex2;}}else{// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try{
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch(TransactionSystemException ex2){
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);throw ex2;}catch(RuntimeException|Error ex2){
logger.error("Application exception overridden by commit exception", ex);throw ex2;}}}}
// org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback@Overridepublicfinalvoidrollback(TransactionStatus status)throwsTransactionException{// org.springframework.transaction.support.AbstractTransactionStatus#completedif(status.isCompleted()){thrownewIllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");}DefaultTransactionStatus defStatus =(DefaultTransactionStatus) status;// Step into ...processRollback(defStatus,false);}// org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollbackprivatevoidprocessRollback(DefaultTransactionStatus status,boolean unexpected){try{// 不期待回滚的标志位boolean unexpectedRollback = unexpected;try{// Step into ...triggerBeforeCompletion(status);// 具备有保存点// NESTED走这里// ((this.transaction instanceof SmartTransactionObject) &&// ((SmartTransactionObject) this.transaction).isRollbackOnly());if(status.hasSavepoint()){if(status.isDebug()){
logger.debug("Rolling back transaction to savepoint");}// step into ...
status.rollbackToHeldSavepoint();}// 新建的事务(最外层的顶层事务)elseif(status.isNewTransaction()){if(status.isDebug()){
logger.debug("Initiating transaction rollback");}// step into ...doRollback(status);}else{// 作为嵌套的一个子事务参与到外层事务中// Participating in larger transactionif(status.hasTransaction()){// 检查回滚标识 org.springframework.transaction.support.AbstractTransactionStatus#rollbackOnly// 或者有全局的回滚标识if(status.isLocalRollbackOnly()||isGlobalRollbackOnParticipationFailure()){if(status.isDebug()){
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");}// step into ...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");}// 当需要提前失败(不等待外层事务,子事务先异常就先回滚)时,异常回滚才有意义// 直接检查 org.springframework.transaction.support.AbstractPlatformTransactionManager#failEarlyOnGlobalRollbackOnly// Unexpected rollback only matters here if we're asked to fail earlyif(!isFailEarlyOnGlobalRollbackOnly()){
unexpectedRollback =false;}}}catch(RuntimeException|Error ex){triggerAfterCompletion(status,TransactionSynchronization.STATUS_UNKNOWN);throw ex;}// step into ...triggerAfterCompletion(status,TransactionSynchronization.STATUS_ROLLED_BACK);// 还记得有那么一次...反正事务用多了,这个报错信息就不需要多说了// Raise UnexpectedRollbackException if we had a global rollback-only markerif(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");}}finally{// step into ...cleanupAfterCompletion(status);}}
// org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerBeforeCompletionprotectedfinalvoidtriggerBeforeCompletion(DefaultTransactionStatus status){// org.springframework.transaction.support.DefaultTransactionStatus#newSynchronization// true:当前事务需要创建一个新的同步(当前线程的事务与jdbc连接)// 如果是嵌套的子事务的话,就不需要了if(status.isNewSynchronization()){if(status.isDebug()){
logger.trace("Triggering beforeCompletion synchronization");}// step into ...TransactionSynchronizationUtils.triggerBeforeCompletion();}}// org.springframework.transaction.support.TransactionSynchronizationUtils#triggerBeforeCompletionpublicstaticvoidtriggerBeforeCompletion(){// 从线程的threadLocal中获取绑定到线程的TransactionSynchronization(当前线程的事务回调方法)for(TransactionSynchronization synchronization :TransactionSynchronizationManager.getSynchronizations()){try{// step into ...
synchronization.beforeCompletion();}catch(Throwable tsex){
logger.error("TransactionSynchronization.beforeCompletion threw exception", tsex);}}}// org.mybatis.spring.SqlSessionUtils.SqlSessionSynchronization#beforeCompletion@OverridepublicvoidbeforeCompletion(){// Issue #18 Close SqlSession and deregister it now// because afterCompletion may be called from a different threadif(!this.holder.isOpen()){
LOGGER
.debug(()->"Transaction synchronization deregistering SqlSession ["+this.holder.getSqlSession()+"]");// 解绑当前线程的连接,从threadLocal中除名TransactionSynchronizationManager.unbindResource(sessionFactory);// 取消TransactionSynchronization的连接活跃标志位this.holderActive =false;
LOGGER.debug(()->"Transaction synchronization closing SqlSession ["+this.holder.getSqlSession()+"]");// 释放这个连接this.holder.getSqlSession().close();}}
// org.springframework.transaction.support.AbstractTransactionStatus#rollbackToHeldSavepointpublicvoidrollbackToHeldSavepoint()throwsTransactionException{Object savepoint =getSavepoint();if(savepoint ==null){thrownewTransactionUsageException("Cannot roll back to savepoint - no savepoint associated with current transaction");}// step into ...getSavepointManager().rollbackToSavepoint(savepoint);getSavepointManager().releaseSavepoint(savepoint);setSavepoint(null);}// org.springframework.jdbc.datasource.JdbcTransactionObjectSupport#rollbackToSavepoint@OverridepublicvoidrollbackToSavepoint(Object savepoint)throwsTransactionException{ConnectionHolder conHolder =getConnectionHolderForSavepoint();try{
conHolder.getConnection().rollback((Savepoint) savepoint);// this.rollbackOnly = false;
conHolder.resetRollbackOnly();}catch(Throwable ex){thrownewTransactionSystemException("Could not roll back to JDBC savepoint", ex);}// step out ...}
// org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback@OverrideprotectedvoiddoRollback(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{// step into ...
con.rollback();}catch(SQLException ex){thrownewTransactionSystemException("Could not roll back JDBC transaction", ex);}}// com.zaxxer.hikari.pool.ProxyConnection#rollback()// 这里是spring默认的连接池的实现// 还有可能是druid啥的@Overridepublicvoidrollback()throwsSQLException{
delegate.rollback();
isCommitStateDirty =false;
lastAccess =currentTime();// step out ...}
// org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCompletionprivatevoidtriggerAfterCompletion(DefaultTransactionStatus status,int completionStatus){// 看得出来:跟triggerBeforeCompletion()是对好兄弟了// 同理,子事务是不需要走这里的if(status.isNewSynchronization()){// Set<TransactionSynchronization> synchs = synchronizations.get();List<TransactionSynchronization> synchronizations =TransactionSynchronizationManager.getSynchronizations();// step into ...TransactionSynchronizationManager.clearSynchronization();if(!status.hasTransaction()|| status.isNewTransaction()){if(status.isDebug()){
logger.trace("Triggering afterCompletion synchronization");}// step into ...// 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);}}}// org.springframework.transaction.support.TransactionSynchronizationManager#clearSynchronizationpublicstaticvoidclearSynchronization()throwsIllegalStateException{// synchronizations.get() != nullif(!isSynchronizationActive()){thrownewIllegalStateException("Cannot deactivate transaction synchronization - not active");}
logger.trace("Clearing transaction synchronization");
synchronizations.remove();// step out ...}// org.springframework.transaction.support.AbstractPlatformTransactionManager#invokeAfterCompletionprotectedfinalvoidinvokeAfterCompletion(List<TransactionSynchronization> synchronizations,int completionStatus){// step into ...TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus);}// org.springframework.transaction.support.TransactionSynchronizationUtils#invokeAfterCompletionpublicstaticvoidinvokeAfterCompletion(@NullableList<TransactionSynchronization> synchronizations,int completionStatus){if(synchronizations !=null){for(TransactionSynchronization synchronization : synchronizations){try{// step into ...
synchronization.afterCompletion(completionStatus);}catch(Throwable tsex){
logger.error("TransactionSynchronization.afterCompletion threw exception", tsex);}}}}// org.mybatis.spring.SqlSessionUtils.SqlSessionSynchronization#afterCompletion// mybatis的源码缩进真有意思@OverridepublicvoidafterCompletion(int status){// triggerBeforeCompletion()里面已经提前置false了if(this.holderActive){// afterCompletion may have been called from a different thread// so avoid failing if there is nothing in this one
LOGGER
.debug(()->"Transaction synchronization deregistering SqlSession ["+this.holder.getSqlSession()+"]");TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory);this.holderActive =false;
LOGGER.debug(()->"Transaction synchronization closing SqlSession ["+this.holder.getSqlSession()+"]");this.holder.getSqlSession().close();}this.holder.reset();// step out ...}}// org.springframework.transaction.support.ResourceHolderSupport#reset@Overridepublicvoidreset(){// step into ...clear();this.referenceCount =0;}// org.springframework.transaction.support.ResourceHolderSupport#clearpublicvoidclear(){this.synchronizedWithTransaction =false;this.rollbackOnly =false;this.deadline =null;// step out ...}