javascript
Spring 事务提交回滚源码解析
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
前言
在上篇文章?Spring 事務(wù)初始化源碼分析 中分析了 Spring 事務(wù)初始化的一個過程,當(dāng)初始化完成后,Spring 是如何去獲取事務(wù),當(dāng)目標(biāo)方法異常后,又是如何進行回滾的,又或是目標(biāo)方法執(zhí)行成功后,又是怎么提交的呢?此外,事務(wù)的提交和回滾由底層數(shù)據(jù)庫進行控制,而在?Spring 事務(wù)使用詳解?中知道,Spring 事務(wù)行為可以傳播,這個傳播方式由 Spring 來進行控制,它是怎么控制的呢?這篇文章就來分析下 Spring 事務(wù)提交回滾的源碼。
TransactionInterceptor
還記得在??Spring 事務(wù)初始化源碼分析 中注冊了一個 bean,名字為?TransactionInterceptor 嗎?,它就是用來執(zhí)行事務(wù)功能的,它是一個方法攔截器,如下所示:
它實現(xiàn)了 MethodInterceptor 接口,而該接口只有一個 invoke 方法,用來執(zhí)行目標(biāo)方法
public Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = (invocation.getThis() != null ?AopUtils.getTargetClass(invocation.getThis()) : null);// 調(diào)用父類的方法return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }父類的?invokeWithinTransaction 方法定義了一個事務(wù)方法執(zhí)行的框架,而每一步再細分為方法進行實現(xiàn),代碼如下:
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation){// 1. 獲取事務(wù)屬性TransactionAttributeSource tas = getTransactionAttributeSource();final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);// 2. 獲取事務(wù)管理器final PlatformTransactionManager tm = determineTransactionManager(txAttr);// 3. 獲取需要事務(wù)的方法名稱:類目.方法名final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);// 4. 聲明式事務(wù)if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {// 5. 獲取該方法上事務(wù)的信息TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal = null;try {// 6. 目標(biāo)方法執(zhí)行,它是一個攔截器鏈retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {// 7. 事務(wù)回滾completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {// 8. 清除事務(wù)信息cleanupTransactionInfo(txInfo);}// 9. 事務(wù)提交commitTransactionAfterReturning(txInfo);return retVal;}else {// 10. 編程式事務(wù),流程和聲明式事務(wù)一致} }一個事務(wù)方法執(zhí)行流程大概有以下幾個步驟:
1. 獲取事務(wù)屬性
2. 獲取事務(wù)管理器
3. 獲取需要事務(wù)的方法名稱
5. 獲取該方法上事務(wù)的信息
6. 目標(biāo)方法執(zhí)行
7. 事務(wù)回滾
8. 清除事務(wù)信息
9. 事務(wù)提交
獲取事務(wù)屬性
首先去獲取方法上面 Translational 注解的屬性,在?Spring 事務(wù)初始化源碼分析?中已經(jīng)分析過了,即在?AnnotationTransactionAttributeSource.computeTransactionAttribute 中進行獲取。
獲取事務(wù)管理器
每個事務(wù)都由對應(yīng)的事務(wù)管理器,所以在事務(wù)開始錢需要獲取對應(yīng)的事務(wù)管理器
protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {if (txAttr == null || this.beanFactory == null) {return getTransactionManager();}// 事務(wù)管理器名稱String qualifier = txAttr.getQualifier();if (StringUtils.hasText(qualifier)) {return determineQualifiedTransactionManager(this.beanFactory, qualifier);}else if (StringUtils.hasText(this.transactionManagerBeanName)) {return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);}else {// 默認事務(wù)管理器PlatformTransactionManager defaultTransactionManager = getTransactionManager();defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);// .....return defaultTransactionManager;} }獲取需要事務(wù)的方法名稱
這里主要去獲取名稱的名稱,為 全限定類名+方法名的方式:method.getDeclaringClass().getName() + '.' + method.getName();
獲取方法上事務(wù)的信息
該部分是 Spring 事務(wù)最復(fù)雜的部分,比如說去創(chuàng)建一個事務(wù),設(shè)置事務(wù)的隔離級別,超時時間,對事務(wù)傳播方式的處理,事務(wù)的掛起和恢復(fù)等;事務(wù)信息 TransactionInfo 包含了目標(biāo)方法執(zhí)行前的所有狀態(tài)信息,如果方法執(zhí)行失敗,則會根據(jù)該信息來進行回滾。
對應(yīng)方法為:
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);代碼如下所示:
創(chuàng)建事務(wù)
protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm,TransactionAttribute txAttr, final String joinpointIdentification) {// 設(shè)置事務(wù)的名稱,為方法全限定名joinpointIdentificationif (txAttr != null && txAttr.getName() == null) {txAttr = new DelegatingTransactionAttribute(txAttr) {public String getName() {return joinpointIdentification;}};}TransactionStatus status = null;if (txAttr != null) {if (tm != null) {// 獲取事務(wù)status = tm.getTransaction(txAttr);}}// 創(chuàng)建事務(wù)信息return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }獲取事務(wù)
在方法 getTransaction 中獲取事務(wù),是最為復(fù)雜的邏輯,在其中處理隔離級別,超時時間和傳播方式等。
public final TransactionStatus getTransaction(TransactionDefinition definition){// 獲取事務(wù)Object transaction = doGetTransaction();// ...// 如果已經(jīng)存在事務(wù)了,則處理事務(wù)的傳播方式,如掛起存在的事務(wù),新建事務(wù)等if (isExistingTransaction(transaction)) {return handleExistingTransaction(definition, transaction, debugEnabled);}// .....// 如果不存在事務(wù),且事務(wù)的傳播方式為 mandatory, 則拋出異常if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {throw new IllegalTransactionStateException("....");}else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {SuspendedResourcesHolder suspendedResources = suspend(null);// 如果事務(wù)的傳播方式為 requested, requestes_new,nested,則會新建一個事務(wù)try {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);// 第三個參數(shù)為true表示新建事務(wù)DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);// 構(gòu)造 transaction,包括隔離級別,timeout,如果是新連接,則綁定到當(dāng)前線程doBegin(transaction, definition);// 同步新事務(wù)prepareSynchronization(status, definition);return status;}catch (RuntimeException | Error ex) {resume(null, suspendedResources);throw ex;}}else {boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);} }獲取事務(wù)?doGetTransaction(),在該方法中,會根據(jù) DataSource 獲取一個連接,如下:
protected Object doGetTransaction() {DataSourceTransactionObject txObject = new DataSourceTransactionObject();//如果設(shè)置了允許嵌套事務(wù),則開啟保存點;只有嵌套事務(wù)才有保存點txObject.setSavepointAllowed(isNestedTransactionAllowed());// 根據(jù) DataSource 獲取連接,ConnectionHolder為一個數(shù)據(jù)庫連接ConnectionHolder conHolder = TransactionSynchronizationManager.getResource(obtainDataSource());txObject.setConnectionHolder(conHolder, false);return txObject; }之后,判斷當(dāng)前線程是否存在事務(wù),如果存在事務(wù),則根據(jù)事務(wù)的傳播方式來處理已存在的事務(wù),這里先不看。
如果不存在事務(wù)且事務(wù)的傳播方式為 requested, requestes_new,nested,則會新建一個事務(wù):
DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //definition事務(wù)屬性 //transaction事務(wù) //newTransaction是否事務(wù)新事務(wù) //suspendedResources需要掛起的事務(wù) protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, Object transaction, boolean newTransaction,boolean newSynchronization, boolean debug, Object suspendedResources) {boolean actualNewSynchronization = newSynchronization &&!TransactionSynchronizationManager.isSynchronizationActive();return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization,definition.isReadOnly(), debug, suspendedResources); }當(dāng)獲取到一個新的事務(wù)后,需要設(shè)置事務(wù)的一些信息,比如隔離級別,timeout 等,這些功能不是由 Spring 來控制,而是由底層的數(shù)據(jù)庫來控制的,數(shù)據(jù)庫連接的設(shè)置是在 doBegin 方法中進行處理:
protected void doBegin(Object transaction, TransactionDefinition definition) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 數(shù)據(jù)庫連接Connection con = null;//如果當(dāng)前事務(wù)不存在數(shù)據(jù)庫連接,或者,當(dāng)前連接的事務(wù)同步設(shè)置為 true,則需要獲取新的數(shù)據(jù)庫連接if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {// 獲取新連接Connection newCon = obtainDataSource().getConnection();// 事務(wù)綁定新連接txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}txObject.getConnectionHolder().setSynchronizedWithTransaction(true);con = txObject.getConnectionHolder().getConnection();// 獲取和設(shè)置隔離級別Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);// 由 Spring 來控制提交方式if (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);con.setAutoCommit(false);}prepareTransactionalConnection(con, definition);// 設(shè)置當(dāng)前線程存在事務(wù)的標(biāo)志txObject.getConnectionHolder().setTransactionActive(true);// 獲取和設(shè)置超時時間int timeout = determineTimeout(definition);if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}//如果是新連接,則綁定到當(dāng)前線程if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());}//其他代碼...... }// ====獲取隔離級別 public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition){// 設(shè)置只讀標(biāo)識if (definition != null && definition.isReadOnly()) {con.setReadOnly(true);//....}// 獲取隔離級別Integer previousIsolationLevel = null;if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {// 從數(shù)據(jù)庫連接獲取隔離級別int currentIsolation = con.getTransactionIsolation();if (currentIsolation != definition.getIsolationLevel()) {previousIsolationLevel = currentIsolation;con.setTransactionIsolation(definition.getIsolationLevel());}}return previousIsolationLevel; }當(dāng)設(shè)置完事務(wù)的信息后,需要把事務(wù)信息記錄在當(dāng)前線程中:
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {if (status.isNewSynchronization()) {TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?definition.getIsolationLevel() : null);TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());TransactionSynchronizationManager.initSynchronization();} }現(xiàn)在來處理已經(jīng)存在事務(wù)的情況,
if (isExistingTransaction(transaction)) {return handleExistingTransaction(definition, transaction, debugEnabled); }判斷是否存在事務(wù),依據(jù)是事務(wù)中有連接,且?TransactionActive 為 true
protected boolean isExistingTransaction(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive()); }如果已經(jīng)存在事務(wù),則會根據(jù)事務(wù)的傳播方式來進行處理,比如 requires_new, nested 等是如何處理:
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction){// 如果傳播方式為 never, 則拋異常if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException("...");}// 如果傳播方式為 not_supported, 則把當(dāng)前存在的事務(wù)掛起if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {// 掛起當(dāng)前事務(wù)Object suspendedResources = suspend(transaction);boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);}// 如果傳播方式為 requires_new, 則掛起當(dāng)前事務(wù),新建一個新事務(wù)if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {// 掛起當(dāng)前事務(wù)SuspendedResourcesHolder suspendedResources = suspend(transaction);// 如果還沒有激活事務(wù),則新建事務(wù)boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);// 設(shè)置數(shù)據(jù)庫的隔離級別,timeout等doBegin(transaction, definition);prepareSynchronization(status, definition);return status;//....}// 如果傳播方式為 nested,則新建事務(wù),但是不會把存在的事務(wù)掛起,它是一個子事務(wù)if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {// 如果不支持嵌套事務(wù),拋異常if (!isNestedTransactionAllowed()) {throw new NestedTransactionNotSupportedException("");}// 如果支持保存點,則創(chuàng)建保存點if (useSavepointForNestedTransaction()) {DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);// 創(chuàng)建保存點 status.createAndHoldSavepoint();return status;}else {// 如果不支持保存點,則和 requires_new 是一樣的boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}}// 如果傳播方式為 supports和requiredboolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }掛起事務(wù),就是把當(dāng)前事務(wù)的狀態(tài)記錄下來,后續(xù)在對該事務(wù)進行恢復(fù)。
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {if (TransactionSynchronizationManager.isSynchronizationActive()) {List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();Object suspendedResources = null;if (transaction != null) {suspendedResources = doSuspend(transaction);}String name = TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}//..... } // 掛起事務(wù)doSuspend protected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 把事務(wù)的連接置空txObject.setConnectionHolder(null);// 從當(dāng)前線程中移除return TransactionSynchronizationManager.unbindResource(obtainDataSource()); }當(dāng)經(jīng)過上面一系列操作獲取到事務(wù)信息后,再根據(jù)事務(wù)信息來封裝到 TransactionInfo 中:
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,TransactionAttribute txAttr, String joinpointIdentification,TransactionStatus status) {// 封裝事務(wù)信息TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);if (txAttr != null) {// 設(shè)置事務(wù)狀態(tài)txInfo.newTransactionStatus(status);} }事務(wù)回滾
到這里,目標(biāo)方法執(zhí)行之前的事務(wù)準(zhǔn)備工作都已做好了,之后,會調(diào)用?InvocationCallback.proceedWithInvocation 來執(zhí)行目標(biāo)方法,如果執(zhí)行失敗,則會進行事務(wù)的回滾操作:
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.getTransactionStatus() != null) {// 判斷異常是不是 RunntimeException 和 Errorif (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {// 回滾事務(wù)txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());// .........}else {// 如果是其他類型的異常,則正常提交txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());// .......}} }//判斷是否回滾的異常,當(dāng)前可以通過rolbackFor屬性來修改 public boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error); }回滾事務(wù)
public final void rollback(TransactionStatus status){// 如果事務(wù)已完成,則回滾會拋異常if (status.isCompleted()) {throw new IllegalTransactionStateException("....");}DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;processRollback(defStatus, false); }// 回滾事務(wù) private void processRollback(DefaultTransactionStatus status, boolean unexpected) {try {boolean unexpectedRollback = unexpected;// 自定義觸發(fā)器的調(diào)用,不知道干嘛用???triggerBeforeCompletion(status);// 如果有保存點,則回滾到保存點if (status.hasSavepoint()) {status.rollbackToHeldSavepoint();}else if (status.isNewTransaction()) {// 如果當(dāng)前事務(wù)為獨立的事務(wù),則回滾doRollback(status);}else {// 如果一個事務(wù)中又有事務(wù),如 required,該事務(wù)可以看作一個事務(wù)鏈,//那么當(dāng)其中的一個事務(wù)需要回滾的時候,并不是立馬進行回滾,//而是只是設(shè)置回滾狀態(tài),到最后再統(tǒng)一回滾if (status.hasTransaction()) {if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {// 只是設(shè)置回滾狀態(tài)doSetRollbackOnly(status);}}//.......}//..........}finally {// 清空記錄并恢復(fù)被掛起的事務(wù)cleanupAfterCompletion(status);} }事務(wù)的回滾操作,如果是嵌套事務(wù),且有保存點的話,直接回滾到保存點,嵌套事務(wù)的回滾不會影響到外部事務(wù),也就是說,外部事務(wù)不會回滾。回滾到保存點是根據(jù)底層數(shù)據(jù)庫來操作的:
public void rollbackToHeldSavepoint() throws TransactionException {Object savepoint = getSavepoint();// 回滾到保存點getSavepointManager().rollbackToSavepoint(savepoint);// 釋放保存點getSavepointManager().releaseSavepoint(savepoint);setSavepoint(null); } // 回滾到保存點 public void rollbackToSavepoint(Object savepoint) throws TransactionException {ConnectionHolder conHolder = getConnectionHolderForSavepoint();conHolder.getConnection().rollback((Savepoint) savepoint);conHolder.resetRollbackOnly();// ......} // 釋放保存點 public void releaseSavepoint(Object savepoint) throws TransactionException {ConnectionHolder conHolder = getConnectionHolderForSavepoint();conHolder.getConnection().releaseSavepoint((Savepoint) savepoint); }如果沒有保存點,則直接回滾,也是使用數(shù)據(jù)庫的API 來操作的:
protected void doRollback(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();con.rollback(); }還有一種情況,?如果一個事務(wù)中又有事務(wù),如 required, 該事務(wù)可以看作一個事務(wù)鏈,那么當(dāng)其中的一個事務(wù)需要回滾的時候,并不是立馬進行回滾,而是只是設(shè)置回滾狀態(tài),到最后再統(tǒng)一回滾。
事務(wù)回滾后需要對事務(wù)信息進行清除:
private void cleanupAfterCompletion(DefaultTransactionStatus status) {// 設(shè)置完成狀態(tài)status.setCompleted();if (status.isNewSynchronization()) {TransactionSynchronizationManager.clear();}if (status.isNewTransaction()) {// 清除事務(wù)信息doCleanupAfterCompletion(status.getTransaction());}if (status.getSuspendedResources() != null) {// 恢復(fù)被掛起的事務(wù)Object transaction = (status.hasTransaction() ? status.getTransaction() : null);resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());} }清除事務(wù)信息:
protected void doCleanupAfterCompletion(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 從當(dāng)前線程中移除數(shù)據(jù)庫連接if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.unbindResource(obtainDataSource());}//重置數(shù)據(jù)庫連接Connection con = txObject.getConnectionHolder().getConnection();if (txObject.isMustRestoreAutoCommit()) {con.setAutoCommit(true);}DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());// 如果是新連接,則釋放連接if (txObject.isNewConnectionHolder()) {DataSourceUtils.releaseConnection(con, this.dataSource);}txObject.getConnectionHolder().clear(); }恢復(fù)被掛起的事務(wù):
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder){if (resourcesHolder != null) {Object suspendedResources = resourcesHolder.suspendedResources;if (suspendedResources != null) {doResume(transaction, suspendedResources);}List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;if (suspendedSynchronizations != null) {TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);doResumeSynchronization(suspendedSynchronizations);}} } // 恢復(fù)事務(wù),把事務(wù)和當(dāng)前線程綁定 protected void doResume(Object transaction, Object suspendedResources) {TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources); }事務(wù)提交
當(dāng)目標(biāo)方法執(zhí)行成功,沒有拋出異常,則事務(wù)可以正常提交了;但是再上面分析事務(wù)回滾的時候,還有一種情況沒有分析,就是如果一個事務(wù)嵌套再一個事務(wù)里面,是一個事務(wù)鏈,如果其中的某個事務(wù)需要回滾,它并不會真正的立馬進行回滾,而是設(shè)置一個回滾標(biāo)識,由最外層的事務(wù)來統(tǒng)一進行回滾;所以再提交事務(wù)之前,還需要進行判斷。
public final void commit(TransactionStatus status) throws TransactionException {// 如果事務(wù)已完成,則不能提交if (status.isCompleted()) {throw new IllegalTransactionStateException("...");}// 判斷嵌套事務(wù)是否設(shè)置了回滾標(biāo)識,如果嵌套事務(wù)設(shè)置了回滾標(biāo)識,則整個事務(wù)鏈都不會提交DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;if (defStatus.isLocalRollbackOnly()) {processRollback(defStatus, false);return;}if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {processRollback(defStatus, true);return;}// 提交事務(wù)processCommit(defStatus); }提交事務(wù):
private void processCommit(DefaultTransactionStatus status) throws TransactionException {try {//.....// 如果由保存點則釋放保存點if (status.hasSavepoint()) { unexpectedRollback = status.isGlobalRollbackOnly();status.releaseHeldSavepoint();}else if (status.isNewTransaction()) {unexpectedRollback = status.isGlobalRollbackOnly();// 提交doCommit(status);}}catch (RuntimeException | Error ex) {// 如果提交過程中出現(xiàn)異常,則還是會回滾doRollbackOnCommitException(status, ex);throw ex;}// ......... } // 數(shù)據(jù)庫連接進行回滾 protected void doCommit(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();con.commit(); }到這里,Spring 事務(wù)的獲取,提交,回滾去分析完畢了,流程還是比較清除的
可以關(guān)注本人公眾號查看更多文章:Java技術(shù)大雜燴
轉(zhuǎn)載于:https://my.oschina.net/mengyuankan/blog/3003783
總結(jié)
以上是生活随笔為你收集整理的Spring 事务提交回滚源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 弹窗时候禁止页面滚动
- 下一篇: 【洛谷 P4051】 [JSOI2007