最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring事務之事務掛起和事務恢復源碼解讀

 更新時間:2022年11月21日 11:01:25   作者:小小少年_  
這篇文章主要介紹了spring事務之事務掛起和事務恢復源碼解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

事務掛起和事務恢復源碼解讀

在學習spring事務的時候,一定會涉及到一個概念,無法避免的,就是事務掛起和事務恢復

對于事務掛起和事務恢復,可以簡單的描述一下,是這樣的

  • 1.首先我們假設有兩個類,A類和B類,兩個類中的字段是一模一樣的,A類表示當前事務,B類表示備份事務
  • 2.如果我開啟一個事務,會把當前事務信息,存入到A類中,如果我這時候要進行事務掛起
  • 3.事務掛起:就會把A類中當前事務的信息,賦值到B類中,然后在創(chuàng)建一個新事務的時候,會賦值到A類中
  • 4.恢復事務:如果此時我當前事務執(zhí)行完畢了,需要恢復原來的事務,就只需要將A類清空,然后將B類中的數(shù)據(jù)信息賦值到A類,此時A事務就會再次生效

我覺得可以理解為就是倒騰了一手

事務掛起源碼

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

我們直接跳入到這個方法中來看,這個方法是在當前事務存在的時候,會進入到這個方法來處理,執(zhí)行鏈路是這樣的

org.springframework.transaction.interceptor.TransactionInterceptor#invoke
    org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
        org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary
            org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
                org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

正常的話,一個事務方法的執(zhí)行是這個鏈路,自己debug看下即可,但是要進入到這個方法中,有一個前提,就是當前事務已存在,然后又調(diào)用了另外一個事務方法,才會進入到這里

我們以PROPAGATION_REQUIRES_NEW這個級別的傳播機制為例,為什么以這個為例,因為這個傳播機制,在當前事務存在的時候,是會將當前事務掛起,然后開啟一個新的事務,也正好可以看下spring是如何掛起事務,并創(chuàng)建新事務的

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
	if (debugEnabled) {
		logger.debug("Suspending current transaction, creating new transaction with name [" +
				definition.getName() + "]");
	}
	/**
	 * 這里是掛起事務的操作,掛起事務的話,會把事務管理器中的屬性設置為null
	 * ,然后將事務管理器中的屬性暫時存儲到suspendedResourceHolder中
	 */
	SuspendedResourcesHolder suspendedResources = suspend(transaction);
	try {
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		// 開啟事務
		doBegin(transaction, definition);
		// 將事務綁定到線程中
		prepareSynchronization(status, definition);
		return status;
	}
	catch (RuntimeException | Error beginEx) {
		/**
		 * 如果在開啟新的事務的時候,異常了,就會在下面這個方法中,將事務恢復(和上面掛起是相對的)
		 * ,其實就是把suspendResourceHolder中的屬性重新賦值到TransactionSynchronizationManager
		 */
		resumeAfterBeginException(transaction, suspendedResources, beginEx);
		throw beginEx;
	}
}

由于這個方法中,代碼比較多,我就刪減了一部分,只留下了propagation_requires_new這個傳播機制的代碼

可以看到,會先調(diào)用suspend(transaction)將當前事務掛起,然后再下面的doBegin()再開啟一個新的事務,然后通過prepareSynchronization(),將事務相關信息放入到threadLocal中

suspend(transaction)

/**
* 這是掛起事務的源碼
 * 所謂的事務掛起:就是將當前事務管理器中的相關屬性,保存到suspendedResourceHolder中
 */
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
	/**
	 * 1.如果當前事務是active狀態(tài),就將事務掛起,掛起的操作其實也簡單
	 * 將當前事務的屬性信息暫存到SuspendedResourcesHolder中,然后將當前事務的屬性設置為null
	 */
	if (TransactionSynchronizationManager.isSynchronizationActive()) {
		List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
		try {
			Object suspendedResources = null;
			if (transaction != null) {
				suspendedResources = doSuspend(transaction);
			}
			/**
			 * 1.1 下面就是掛起事務的操作,將事務同步管理器中的屬性置為null
			 * , 然后將配置信息,存儲到suspendedResources中,以便在恢復事務的時候,可以恢復
			 */
			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);
		}
		catch (RuntimeException | Error ex) {
			/**
			 * 2.如果掛起事務失敗,就需要進行回滾,就是將suspendedResourcesHolder
			 * 中的屬性重新賦值到TransactionSynchronizationManager中
			 */
			// doSuspend failed - original transaction is still active...
			doResumeSynchronization(suspendedSynchronizations);
			throw ex;
		}
	}
	else if (transaction != null) {
		// Transaction active but no synchronization active.
		Object suspendedResources = doSuspend(transaction);
		return new SuspendedResourcesHolder(suspendedResources);
	}
	else {
		// Neither transaction nor synchronization active.
		return null;
	}
}

這是suspend的源碼,可以看到,在1.1這個注釋位置,會獲取到當前事務的屬性信息,然后在下面,會new SuspendedResourcesHolder(),將當前事務屬性信息放入到這里面

再下面,就是一些異常的判斷和處理,我們可以認為,這個方法就是把事務的屬性信息存入到了SuspendedResourcesHolder對象中

newTransactionStatus()

這個方法也很重要,會把剛才創(chuàng)建的suspend對象,放入到DefaultTransactionStatus類中,這里我猜是為了在后面事務恢復的時候用的

doBegin()

在doBegin()方法中,主要是重新獲取一個數(shù)據(jù)庫連接,然后設置連接的相關信息,比如:非自動提交等

然后將連接信息存入到TransactionSynchronizationManager對象中

我們可以簡單認為doBegin()就是重新開啟了一個事務連接

事務恢復

前面講的是事務掛起,下面來說事務恢復,事務恢復,就是在事務提交或者回滾的時候,會進行事務恢復的處理


這里直接貼了一張圖,是事務提交和事務回滾的處理流程,最終都會調(diào)用到cleanupAfterCompletion()方法,這個方法就是事務恢復的代碼

private void cleanupAfterCompletion(DefaultTransactionStatus status) {
		status.setCompleted();
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.clear();
		}
		if (status.isNewTransaction()) {
			doCleanupAfterCompletion(status.getTransaction());
		}
		if (status.getSuspendedResources() != null) {
			if (status.isDebug()) {
				logger.debug("Resuming suspended transaction after completion of inner transaction");
			}
			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
		}
	}

在這個代碼中,前面是一些邏輯處理,應該是對當前事務進行清除的操作,需要關注的是最后一行代碼,resume()方法

protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
			throws TransactionException {

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

這里可以看到,是從resourcesHolder中取一些參數(shù)賦值到TransactionSynchronizationManager中;SuspendedResourcesHolder是哪個對象呢?

就是前面事務掛起的時候,將當前事務參數(shù)信息賦值到的一個對象

所以

我們可以認為,事務掛起就是將事務賦值到一個臨時對象中,事務恢復就是從臨時對象中,將事務屬性信息賦值到當前事務中

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 基于Java制作一個燈謎猜猜樂游戲

    基于Java制作一個燈謎猜猜樂游戲

    中秋佳節(jié),是我國傳統(tǒng)的重大節(jié)日之一,全國各地為了增強過節(jié)的氣氛,都有許多傳統(tǒng)的中秋活動,比如猜燈謎,所以本文就來用Java制作一個燈謎猜猜樂游戲,感興趣的可以了解下
    2023-09-09
  • java構(gòu)造方法的作用總結(jié)

    java構(gòu)造方法的作用總結(jié)

    在本篇文章里小編給大家整理了關于java構(gòu)造方法的相關知識點以及實例代碼,有需要的朋友們可以學習下。
    2019-07-07
  • Spring Security動態(tài)權限的實現(xiàn)方法詳解

    Spring Security動態(tài)權限的實現(xiàn)方法詳解

    這篇文章主要和小伙伴們簡單介紹下 Spring Security 中的動態(tài)權限方案,以便于小伙伴們更好的理解 TienChin 項目中的權限方案,感興趣的可以了解一下
    2022-06-06
  • Java中獲取年份月份的幾種常見方法

    Java中獲取年份月份的幾種常見方法

    這篇文章主要給大家介紹了關于Java中獲取年份月份的幾種常見方法,在開發(fā)應用程序時,經(jīng)常需要獲取當前的年、月、日,并以特定格式進行展示或處理,需要的朋友可以參考下
    2023-09-09
  • Springboot應用gradle?Plugin示例詳解

    Springboot應用gradle?Plugin示例詳解

    這篇文章主要介紹了Springboot應用gradle?Plugin詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • Scala入門教程詳解

    Scala入門教程詳解

    這篇文章主要介紹了Scala入門教程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-06-06
  • springboot中關于自動建表,無法更新字段的問題

    springboot中關于自動建表,無法更新字段的問題

    這篇文章主要介紹了springboot中關于自動建表,無法更新字段的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java實現(xiàn)用戶管理系統(tǒng)

    Java實現(xiàn)用戶管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Java實現(xiàn)用戶管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • springboot項目部署到寶塔的詳細圖文教程

    springboot項目部署到寶塔的詳細圖文教程

    網(wǎng)上關于寶塔運行springBoot的東西說有點迷糊,但是有一句話很重要,Spring boot項目只需要JDK環(huán)境即可部署成功,下面這篇文章主要給大家介紹了關于springboot項目部署到寶塔的詳細圖文教程,需要的朋友可以參考下
    2023-05-05
  • Java二叉樹的四種遍歷(遞歸和非遞歸)

    Java二叉樹的四種遍歷(遞歸和非遞歸)

    這篇文章主要介紹了Java二叉樹的四種遍歷,二叉樹的遍歷可以分為前序、中序、后序、層次遍歷,需要的朋友可以參考下
    2020-12-12

最新評論

临邑县| 滨州市| 叶城县| 科技| 曲沃县| 上杭县| 尖扎县| 华容县| 元氏县| 连平县| 特克斯县| 山阴县| 保靖县| 拜城县| 启东市| 苍溪县| 迭部县| 榆社县| 万安县| 湖北省| 平定县| 桐乡市| 神农架林区| 威海市| 宁乡县| 永春县| 黄山市| 招远市| 吉安县| 平潭县| 朝阳县| 克什克腾旗| 古浪县| 屏山县| 昌宁县| 娄底市| 徐州市| 迁安市| 盐边县| 濉溪县| 城市|