publicabstractclassTransactionAspectSupportimplementsBeanFactoryAware,InitializingBean{protectedObjectinvokeWithinTransaction(Methodmethod,@NullableClass<?>targetClass,finalInvocationCallbackinvocation)throwsThrowable{/*
* TODO 其中事务传播行为的特点(这些特点,仔细分析代码是可以看出来的。相对比较烧脑。一般先了解特点,后面才会看源码):
* PROPAGATION_REQUIRED 如果当前存在事务,假如当前事务。如果不存在事务,新建事务。
* PROPAGATION_REQUIRES_NEW 如果当前存在事务,则挂起当前事务,新建一个事务。如果不存在事务,新建一个事务。使用频率高
* PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前不存在事务,则和PROPAGATION_REQUIRED一样新建事务。
* 特点:外围事务回滚,嵌套事务全部回滚。嵌套事务回滚,如果在外围中捕获了,则仅仅回滚嵌套事务。
* PROPAGATION_MANDATORY 以事务方式运行,如果当前不存在事务,则抛出异常
* PROPAGATION_NEVER 以非事务方式运行,如果当前存在事务,则抛出异常
* PROPAGATION_SUPPORTEDS 支持事务。如果当前存在事务,加入当前事务。如果不存在事务,则以非事务方式运行。
* PROPAGATION_NOT_SUPPORTED 以非事务方式运行。如果当前存在事务,挂起当前事务。
*/// 事务属性的获取// If the transaction attribute is null, the method is non-transactional.TransactionAttributeSourcetas=getTransactionAttributeSource();// TODO getTransactionAttribute中是获取事务注解属性的具体逻辑。finalTransactionAttributetxAttr=(tas!=null?tas.getTransactionAttribute(method,targetClass):null);// 获取事务管理器finalPlatformTransactionManagertm=determineTransactionManager(txAttr);finalStringjoinpointIdentification=methodIdentification(method,targetClass,txAttr);if(txAttr==null||!(tminstanceofCallbackPreferringPlatformTransactionManager)){// TODO 重点:如果有必要,创建事务// Standard transaction demarcation with getTransaction and commit/rollback calls.TransactionInfotxInfo=createTransactionIfNecessary(tm,txAttr,joinpointIdentification);ObjectretVal=null;try{// 上层方法中传入的回调函数,这里面是AOP执行链,火炬传递,直到调用了业务方法// 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(Throwableex){// 业务方法执行出现异常// target invocation exceptioncompleteTransactionAfterThrowing(txInfo,ex);throwex;}finally{// TODO 清除事务信息,将当前事务清除,如果存在旧的事务对象,将旧的事务对象设置为当前持有的事务// 存储在TransactionAspectSupport.transactionInfoHolder中,这是一个静态TrheadLocal常量。cleanupTransactionInfo(txInfo);}// TODO 提交事务commitTransactionAfterReturning(txInfo);returnretVal;}else{// 此处省略...}}}
publicabstractclassAbstractPlatformTransactionManagerimplementsPlatformTransactionManager,Serializable{@OverridepublicfinalTransactionStatusgetTransaction(@NullableTransactionDefinitiondefinition)throwsTransactionException{// 获取事务对象Objecttransaction=doGetTransaction();// Cache debug flag to avoid repeated checks.booleandebugEnabled=logger.isDebugEnabled();if(definition==null){// Use defaults if no transaction definition given.definition=newDefaultTransactionDefinition();}// 判断是否已经存在事务。如果当前事务对象已经持有了链接,并且事务是活跃状态,则表示已经存在事务。// 如果当前已经存在事务,按照已存在事务的方式判断传播行为,进行处理if(isExistingTransaction(transaction)){// Existing transaction found -> check propagation behavior to find out how to behave.// TODO 如果当前已存在事务,会走到此方法逻辑进行处理。returnhandleExistingTransaction(definition,transaction,debugEnabled);}// TODO 以下是针对前一个方法未开启事务的情况的处理。// 检测事务的超时时间设置是否正确// Check definition settings for new transaction.if(definition.getTimeout()<TransactionDefinition.TIMEOUT_DEFAULT){thrownewInvalidTimeoutException("Invalid transaction timeout",definition.getTimeout());}// 如果传播属性是PROPAGATION_MANDATORY,且当前不存在事务,则抛出异常// No existing transaction found -> check propagation behavior to find out how to proceed.if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_MANDATORY){thrownewIllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");}// 如果传播属性是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED时,会走到这里elseif(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRED||definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW||definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){// 因为以上三种事务传播属性的特性,这里会挂起(如果当前存在事务)SuspendedResourcesHoldersuspendedResources=suspend(null);if(debugEnabled){logger.debug("Creating new transaction with name ["+definition.getName()+"]: "+definition);}try{booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);// 创建事务状态对象DefaultTransactionStatusstatus=newTransactionStatus(definition,transaction,true,newSynchronization,debugEnabled,suspendedResources);// TODO 重点:开启事务。按照当前测试代码注册的事务管理器,使用的是DataSourceTransactionManagerdoBegin(transaction,definition);// 如果是新开启的事务,设置事务管理器相关属性。其实走到这里的代码,一定是新启的事务。// 因为前面已经判断了,如果存在事务,就走handleExistingTransaction方法prepareSynchronization(status,definition);returnstatus;}catch(RuntimeException|Errorex){resume(null,suspendedResources);throwex;}}else{// 以非事务方式运行 NEVER SUPPORTS NOT_SUPPORTED,在外围未开启事务时,会走这里。// Create "empty" transaction: no actual transaction, but potentially synchronization.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);}booleannewSynchronization=(getTransactionSynchronization()==SYNCHRONIZATION_ALWAYS);returnprepareTransactionStatus(definition,null,true,newSynchronization,debugEnabled,null);}}}
publicabstractclassAbstractPlatformTransactionManagerimplementsPlatformTransactionManager,Serializable{privateTransactionStatushandleExistingTransaction(TransactionDefinitiondefinition,Objecttransaction,booleandebugEnabled)throwsTransactionException{// 如果当前方法传播属性为从不开启事务,直接抛出异常。// PROPAGATION_NEVER特性决定,如果当前存在事务,则抛出异常if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NEVER){thrownewIllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}// PROPAGATION_NOT_SUPPORTED特性:如果当前存在事务,挂起当前事务,以非事务方式运行if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NOT_SUPPORTED){if(debugEnabled){logger.debug("Suspending current transaction");}// 挂起事务ObjectsuspendedResources=suspend(transaction);booleannewSynchronization=(getTransactionSynchronization()==SYNCHRONIZATION_ALWAYS);// 返回事务状态对象returnprepareTransactionStatus(definition,null,false,newSynchronization,debugEnabled,suspendedResources);}// TODO 重点:PROPAGATION_REQUIRES_NEW特性:无论当前是否存在事务,都新建一个事务。// 如果存在事务,将会把当前事务挂起,被挂起的事务会存储到新的事务状态对象中。if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW){if(debugEnabled){logger.debug("Suspending current transaction, creating new transaction with name ["+definition.getName()+"]");}// 挂起当前事务,由于PROPAGATION_REQUIRES_NEW的特性,需要使用新的事务,所以要将当前事务挂起,当新的事务执行完毕时,会恢复这个挂起的事务。SuspendedResourcesHoldersuspendedResources=suspend(transaction);try{booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);// TODO 可以看到,这里创建事务对象时,构造函数中的参数newTransaction为true。DefaultTransactionStatusstatus=newTransactionStatus(definition,transaction,true,newSynchronization,debugEnabled,suspendedResources);// PROPAGATION_REQUIRES_NEW表示总是新启一个事务,这里会新开启事务。doBegin(transaction,definition);prepareSynchronization(status,definition);returnstatus;}catch(RuntimeException|ErrorbeginEx){resumeAfterBeginException(transaction,suspendedResources,beginEx);throwbeginEx;}}// TODO PROPAGATION_NESTED嵌套事务,如果存在事务,则在嵌套事务中运行。如果不存在事务,则新建一个事务。// 嵌套事务是用savePoint来实现的。具体过程:// 1.新建事务状态对象时,会设置一个保存点(或者叫回滚点)。// 2.如果业务方法执行抛出异常,则会被事务切面捕获,如果存在保存点,则会回滚值保存点。// 3.正常执行完业务方法,如果这个方法对应的事务状态对象中具有保存点,则会擦除这个保存点。if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){if(!isNestedTransactionAllowed()){thrownewNestedTransactionNotSupportedException("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()+"]");}// 是否使用保存点,在测试中用到的事务管理器来看,总是返回trueif(useSavepointForNestedTransaction()){// Create savepoint within existing Spring-managed transaction,// through the SavepointManager API implemented by TransactionStatus.// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.DefaultTransactionStatusstatus=prepareTransactionStatus(definition,transaction,false,false,debugEnabled,null);// 创建savePoint,保存点(或者叫回滚点)status.createAndHoldSavepoint();returnstatus;}else{booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);DefaultTransactionStatusstatus=newTransactionStatus(definition,transaction,true,newSynchronization,debugEnabled,null);doBegin(transaction,definition);prepareSynchronization(status,definition);returnstatus;}}// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.if(debugEnabled){logger.debug("Participating in existing transaction");}// 省略无关代码...booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);// 创建事务状态对象,如果是新创建的事务,则设置事务管理器的相关属性。returnprepareTransactionStatus(definition,transaction,false,newSynchronization,debugEnabled,null);}}
publicclassDataSourceTransactionManagerextendsAbstractPlatformTransactionManagerimplementsResourceTransactionManager,InitializingBean{protectedvoiddoBegin(Objecttransaction,TransactionDefinitiondefinition){DataSourceTransactionObjecttxObject=(DataSourceTransactionObject)transaction;Connectioncon=null;try{// 如果当前事务对象没有持有链接,就获取一个,并设置到链接持有变量中。if(!txObject.hasConnectionHolder()||txObject.getConnectionHolder().isSynchronizedWithTransaction()){ConnectionnewCon=obtainDataSource().getConnection();if(logger.isDebugEnabled()){logger.debug("Acquired Connection ["+newCon+"] for JDBC transaction");}txObject.setConnectionHolder(newConnectionHolder(newCon),true);}// 设置事务同步为true,标识使用了事务。txObject.getConnectionHolder().setSynchronizedWithTransaction(true);// 获取数据库连接对象。con=txObject.getConnectionHolder().getConnection();// 设置事务隔离级别IntegerpreviousIsolationLevel=DataSourceUtils.prepareConnectionForTransaction(con,definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);// TODO 重点:开启事务核心点:将事务自动提交关闭。即手动提交事务(由spring控制事务提交)// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,// so we don't want to do it unnecessarily (for example if we've explicitly// configured the connection pool to set it already).if(con.getAutoCommit()){txObject.setMustRestoreAutoCommit(true);if(logger.isDebugEnabled()){logger.debug("Switching JDBC Connection ["+con+"] to manual commit");}con.setAutoCommit(false);}// 如果Transaction中配置了只读,这里会将事务设置为只读属性prepareTransactionalConnection(con,definition);// 在事务链接持有对象中,设置事务活跃状态为truetxObject.getConnectionHolder().setTransactionActive(true);// 查找配置的事务超时时间,如果未配置,会使用默认的。默认值为-1,表示永不超时。inttimeout=determineTimeout(definition);if(timeout!=TransactionDefinition.TIMEOUT_DEFAULT){// 在链接持有对象中设置超时时间,从这里可以看出,单位是秒。txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}// 如果事务对象是在当前代理方法中new的,则绑定到ThreadLocal变量中。// Bind the connection holder to the thread.if(txObject.isNewConnectionHolder()){TransactionSynchronizationManager.bindResource(obtainDataSource(),txObject.getConnectionHolder());}}catch(Throwableex){// 如果出现异常,释放数据库连接对象。if(txObject.isNewConnectionHolder()){DataSourceUtils.releaseConnection(con,obtainDataSource());txObject.setConnectionHolder(null,false);}thrownewCannotCreateTransactionException("Could not open JDBC Connection for transaction",ex);}}}