Spring 事務提交回滾源碼解析

前言

在上篇文章 Spring 事務初始化源碼分析 中分析了 Spring 事務初始化的一個過程,當初始化完成後,Spring 是如何去獲取事務,當目標方法異常後,又是如何進行回滾的,又或是目標方法執行成功後,又是怎麼提交的呢?此外,事務的提交和回滾由底層數據庫進行控制,而在 Spring 事務使用詳解 中知道,Spring 事務行爲能夠傳播,這個傳播方式由 Spring 來進行控制,它是怎麼控制的呢?這篇文章就來分析下 Spring 事務提交回滾的源碼。java

TransactionInterceptor

還記得在  Spring 事務初始化源碼分析 中註冊了一個 bean,名字爲 TransactionInterceptor 嗎?,它就是用來執行事務功能的,它是一個方法攔截器,以下所示:數據庫

它實現了 MethodInterceptor 接口,而該接口只有一個 invoke 方法,用來執行目標方法編程

public Object invoke(MethodInvocation invocation) throws Throwable {
	Class<?> targetClass = (invocation.getThis() != null ?AopUtils.getTargetClass(invocation.getThis()) : null);
    // 調用父類的方法
	return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

父類的 invokeWithinTransaction 方法定義了一個事務方法執行的框架,而每一步再細分爲方法進行實現,代碼以下:框架

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation){
	// 1. 獲取事務屬性
	TransactionAttributeSource tas = getTransactionAttributeSource();
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
	// 2. 獲取事務管理器
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	// 3. 獲取須要事務的方法名稱:類目.方法名
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
	// 4. 聲明式事務
	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 5. 獲取該方法上事務的信息
		TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
		Object retVal = null;
		try {
			// 6. 目標方法執行,它是一個攔截器鏈
			retVal = invocation.proceedWithInvocation();
		}
		catch (Throwable ex) {
			// 7. 事務回滾
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			// 8. 清除事務信息
			cleanupTransactionInfo(txInfo);
		}
		// 9. 事務提交
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}
	else {
		// 10. 編程式事務,流程和聲明式事務一致
	}
}

一個事務方法執行流程大概有如下幾個步驟:源碼分析

1. 獲取事務屬性
2. 獲取事務管理器
3. 獲取須要事務的方法名稱
5. 獲取該方法上事務的信息
6. 目標方法執行
7. 事務回滾
8. 清除事務信息
9. 事務提交ui

獲取事務屬性

首先去獲取方法上面 Translational 註解的屬性,在 Spring 事務初始化源碼分析 中已經分析過了,即在 AnnotationTransactionAttributeSource.computeTransactionAttribute 中進行獲取。this

獲取事務管理器

每一個事務都由對應的事務管理器,因此在事務開始錢須要獲取對應的事務管理器spa

protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
	if (txAttr == null || this.beanFactory == null) {
		return getTransactionManager();
	}
	// 事務管理器名稱
	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 {
		// 默認事務管理器
		PlatformTransactionManager defaultTransactionManager = getTransactionManager();
		defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
		// .....
		return defaultTransactionManager;
	}
}

獲取須要事務的方法名稱

這裏主要去獲取名稱的名稱,爲 全限定類名+方法名的方式:method.getDeclaringClass().getName() + '.' + method.getName();.net

獲取方法上事務的信息

該部分是 Spring 事務最複雜的部分,好比說去建立一個事務,設置事務的隔離級別,超時時間,對事務傳播方式的處理,事務的掛起和恢復等;事務信息 TransactionInfo 包含了目標方法執行前的全部狀態信息,若是方法執行失敗,則會根據該信息來進行回滾。線程

對應方法爲:

TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

代碼以下所示:

建立事務

protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm,
		TransactionAttribute txAttr, final String joinpointIdentification) {
	// 設置事務的名稱,爲方法全限定名joinpointIdentification
	if (txAttr != null && txAttr.getName() == null) {
		txAttr = new DelegatingTransactionAttribute(txAttr) {
			public String getName() {
				return joinpointIdentification;
			}
		};
	}
	TransactionStatus status = null;
	if (txAttr != null) {
		if (tm != null) {
		    // 獲取事務
			status = tm.getTransaction(txAttr);
		}
	}
	// 建立事務信息
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

獲取事務

在方法 getTransaction 中獲取事務,是最爲複雜的邏輯,在其中處理隔離級別,超時時間和傳播方式等。

public final TransactionStatus getTransaction(TransactionDefinition definition){
	// 獲取事務
	Object transaction = doGetTransaction();
    // ...
	// 若是已經存在事務了,則處理事務的傳播方式,如掛起存在的事務,新建事務等
	if (isExistingTransaction(transaction)) {
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}
	// .....
	
	// 若是不存在事務,且事務的傳播方式爲 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);
		// 若是事務的傳播方式爲 requested, requestes_new,nested,則會新建一個事務
		try {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			// 第三個參數爲true表示新建事務
			DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			// 構造 transaction,包括隔離級別,timeout,若是是新鏈接,則綁定到當前線程
			doBegin(transaction, definition);
			// 同步新事務
			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);
	}
}

獲取事務 doGetTransaction(),在該方法中,會根據 DataSource 獲取一個鏈接,以下:

protected Object doGetTransaction() {
	DataSourceTransactionObject txObject = new DataSourceTransactionObject();
    //若是設置了容許嵌套事務,則開啓保存點;只有嵌套事務纔有保存點
	txObject.setSavepointAllowed(isNestedTransactionAllowed());
    // 根據 DataSource 獲取鏈接,ConnectionHolder爲一個數據庫鏈接
	ConnectionHolder conHolder = TransactionSynchronizationManager.getResource(obtainDataSource());
	txObject.setConnectionHolder(conHolder, false);
	return txObject;
}

以後,判斷當前線程是否存在事務,若是存在事務,則根據事務的傳播方式來處理已存在的事務,這裏先不看。

若是不存在事務且事務的傳播方式爲 requested, requestes_new,nested,則會新建一個事務:

DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//definition事務屬性
//transaction事務
//newTransaction是否事務新事務
//suspendedResources須要掛起的事務
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);
}

當獲取到一個新的事務後,須要設置事務的一些信息,好比隔離級別,timeout 等,這些功能不是由 Spring 來控制,而是由底層的數據庫來控制的,數據庫鏈接的設置是在 doBegin 方法中進行處理:

protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	// 數據庫鏈接
	Connection con = null;
	//若是當前事務不存在數據庫鏈接,或者,當前鏈接的事務同步設置爲 true,則須要獲取新的數據庫鏈接
	if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
		// 獲取新鏈接
		Connection newCon = obtainDataSource().getConnection();
		// 事務綁定新鏈接
		txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
	}
	txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
	con = txObject.getConnectionHolder().getConnection();
	// 獲取和設置隔離級別
	Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
	txObject.setPreviousIsolationLevel(previousIsolationLevel);

	// 由 Spring 來控制提交方式
	if (con.getAutoCommit()) {
		txObject.setMustRestoreAutoCommit(true);
		con.setAutoCommit(false);
	}
	prepareTransactionalConnection(con, definition);
	// 設置當前線程存在事務的標誌
	txObject.getConnectionHolder().setTransactionActive(true);

	// 獲取和設置超時時間
	int timeout = determineTimeout(definition);
	if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
		txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
	}

	//若是是新鏈接,則綁定到當前線程
	if (txObject.isNewConnectionHolder()) {
		TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
	}
	//其餘代碼......
}

// ====獲取隔離級別
public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition){
	// 設置只讀標識
	if (definition != null && definition.isReadOnly()) {
		con.setReadOnly(true);
		//....
	}

	// 獲取隔離級別
	Integer previousIsolationLevel = null;
	if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
		// 從數據庫鏈接獲取隔離級別
		int currentIsolation = con.getTransactionIsolation();
		if (currentIsolation != definition.getIsolationLevel()) {
			previousIsolationLevel = currentIsolation;
			con.setTransactionIsolation(definition.getIsolationLevel());
		}
	}
	return previousIsolationLevel;
}

當設置完事務的信息後,須要把事務信息記錄在當前線程中:

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();
	}
}

如今來處理已經存在事務的狀況,

if (isExistingTransaction(transaction)) {
	return handleExistingTransaction(definition, transaction, debugEnabled);
}

判斷是否存在事務,依據是事務中有鏈接,且 TransactionActive 爲 true

protected boolean isExistingTransaction(Object transaction) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}

若是已經存在事務,則會根據事務的傳播方式來進行處理,好比 requires_new, nested 等是如何處理:

private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction){
	// 若是傳播方式爲 never, 則拋異常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
		throw new IllegalTransactionStateException("...");
	}
	// 若是傳播方式爲 not_supported, 則把當前存在的事務掛起
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
		// 掛起當前事務
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}
	// 若是傳播方式爲 requires_new, 則掛起當前事務,新建一個新事務
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
		// 掛起當前事務
		SuspendedResourcesHolder suspendedResources = suspend(transaction);
		// 若是尚未激活事務,則新建事務
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, 
											newSynchronization, debugEnabled, suspendedResources);
		// 設置數據庫的隔離級別,timeout等
		doBegin(transaction, definition);
		prepareSynchronization(status, definition);
		return status;
		//....
	}
	// 若是傳播方式爲 nested,則新建事務,可是不會把存在的事務掛起,它是一個子事務
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// 若是不支持嵌套事務,拋異常
		if (!isNestedTransactionAllowed()) {
			throw new NestedTransactionNotSupportedException("");
		}
		// 若是支持保存點,則建立保存點
		if (useSavepointForNestedTransaction()) {
			DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, 
											 false, false, debugEnabled, null);
			// 建立保存點								 
			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和required
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

掛起事務,就是把當前事務的狀態記錄下來,後續在對該事務進行恢復。

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);
	}
	//.....
}
// 掛起事務doSuspend
protected Object doSuspend(Object transaction) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	// 把事務的鏈接置空
	txObject.setConnectionHolder(null);
	// 從當前線程中移除
	return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}

當通過上面一系列操做獲取到事務信息後,再根據事務信息來封裝到 TransactionInfo 中:

protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
		TransactionAttribute txAttr, String joinpointIdentification,
		TransactionStatus status) {
	// 封裝事務信息
	TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
	if (txAttr != null) {
		// 設置事務狀態
		txInfo.newTransactionStatus(status);

	}
}

事務回滾

到這裏,目標方法執行以前的事務準備工做都已作好了,以後,會調用 InvocationCallback.proceedWithInvocation 來執行目標方法,若是執行失敗,則會進行事務的回滾操做:

protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
	if (txInfo != null && txInfo.getTransactionStatus() != null) {
		// 判斷異常是否是 RunntimeException 和 Error
		if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
			// 回滾事務
			txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
			// .........
		}
		else {
			// 若是是其餘類型的異常,則正常提交
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
			// .......
		}
	}
}

//判斷是否回滾的異常,當前能夠經過rolbackFor屬性來修改
public boolean rollbackOn(Throwable ex) {
	return (ex instanceof RuntimeException || ex instanceof Error);
}

回滾事務

public final void rollback(TransactionStatus status){
	// 若是事務已完成,則回滾會拋異常
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException("....");
	}
	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
	processRollback(defStatus, false);
}

// 回滾事務
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
	try {
		boolean unexpectedRollback = unexpected;
		// 自定義觸發器的調用,不知道幹嗎用???
		triggerBeforeCompletion(status);
		// 若是有保存點,則回滾到保存點
		if (status.hasSavepoint()) {
			status.rollbackToHeldSavepoint();
		}
		else if (status.isNewTransaction()) {
			// 若是當前事務爲獨立的事務,則回滾
			doRollback(status);
		}
		else {
			// 若是一個事務中又有事務,如 required,該事務能夠看做一個事務鏈,
			//那麼當其中的一個事務須要回滾的時候,並非立馬進行回滾,
			//而是隻是設置回滾狀態,到最後再統一回滾
			if (status.hasTransaction()) {
				if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
					// 只是設置回滾狀態
					doSetRollbackOnly(status);
				}
			}
			//.......
		}
		//..........
	}finally {
		// 清空記錄並恢復被掛起的事務
		cleanupAfterCompletion(status);
	}
}

事務的回滾操做,若是是嵌套事務,且有保存點的話,直接回滾到保存點,嵌套事務的回滾不會影響到外部事務,也就是說,外部事務不會回滾。回滾到保存點是根據底層數據庫來操做的:

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);
}

若是沒有保存點,則直接回滾,也是使用數據庫的API 來操做的:

protected void doRollback(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	con.rollback();
}

還有一種狀況, 若是一個事務中又有事務,如 required, 該事務能夠看做一個事務鏈,那麼當其中的一個事務須要回滾的時候,並非立馬進行回滾,而是隻是設置回滾狀態,到最後再統一回滾。

事務回滾後須要對事務信息進行清除:

private void cleanupAfterCompletion(DefaultTransactionStatus status) {
	// 設置完成狀態
	status.setCompleted();
	if (status.isNewSynchronization()) {
		TransactionSynchronizationManager.clear();
	}
	if (status.isNewTransaction()) {
        // 清除事務信息
		doCleanupAfterCompletion(status.getTransaction());
	}
	if (status.getSuspendedResources() != null) {
		// 恢復被掛起的事務
		Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
		resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
	}
}

清除事務信息:

protected void doCleanupAfterCompletion(Object transaction) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	// 從當前線程中移除數據庫鏈接
	if (txObject.isNewConnectionHolder()) {
		TransactionSynchronizationManager.unbindResource(obtainDataSource());
	}
	//重置數據庫鏈接
	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();
}

恢復被掛起的事務:

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);
		}
	}
}
// 恢復事務,把事務和當前線程綁定
protected void doResume(Object transaction, Object suspendedResources) {
	TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
}

事務提交

當目標方法執行成功,沒有拋出異常,則事務能夠正常提交了;可是再上面分析事務回滾的時候,還有一種狀況沒有分析,就是若是一個事務嵌套再一個事務裏面,是一個事務鏈,若是其中的某個事務須要回滾,它並不會真正的立馬進行回滾,而是設置一個回滾標識,由最外層的事務來統一進行回滾;因此再提交事務以前,還須要進行判斷。

public final void commit(TransactionStatus status) throws TransactionException {
	// 若是事務已完成,則不能提交
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException("...");
	}
	// 判斷嵌套事務是否設置了回滾標識,若是嵌套事務設置了回滾標識,則整個事務鏈都不會提交
	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
	if (defStatus.isLocalRollbackOnly()) {
		processRollback(defStatus, false);
		return;
	}
	if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
		processRollback(defStatus, true);
		return;
	}
	// 提交事務
	processCommit(defStatus);
}

提交事務:

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) {
		// 若是提交過程當中出現異常,則仍是會回滾
		doRollbackOnCommitException(status, ex);
		throw ex;
	}
	// .........
}
// 數據庫鏈接進行回滾
protected void doCommit(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	con.commit();
}

到這裏,Spring 事務的獲取,提交,回滾去分析完畢了,流程仍是比較清除的

能夠關注本人公衆號查看更多文章:Java技術大雜燴

相關文章
相關標籤/搜索