2023-09-16  阅读(43)
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105352276

处理回滚流程图

202309162319417631.png

处理提交流程图

202309162319430852.png

传播机制图

202309162319444823.png

ConnectionHolder的clear连接持有器的清除

继续上一篇的doCleanupAfterCompletion,连接关闭了,最后连接持有器也应该清除状态。

    	@Override
    	public void clear() {
    		super.clear();
    		this.transactionActive = false;
    		this.savepointsSupported = null;
    		this.savepointCounter = 0;
    	}

ResourceHolderSupport的clear

清除事务同步状态,回滚状态等。

    	public void clear() {
    		this.synchronizedWithTransaction = false;
    		this.rollbackOnly = false;
    		this.deadline = null;
    	}

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

DataSourceTransactionManager的doResume

将挂起的事务连接持有器和数据源绑定,放入线程私有变量中。

    @Override
    	protected void doResume(@Nullable Object transaction, Object suspendedResources) {
    		TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
    	}

刚好和上一篇的解除绑定相反,把他们放到resourcesmap中。

202309162319449574.png

TransactionAspectSupport的cleanupTransactionInfo清除事务信息

处理完之后,最后还要清除事务信息:

202309162319454905.png
其实就是恢复线程私有变量的状态,设置回老的,因为前面有绑定线程的时候有设置过新的:

    	protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
    		if (txInfo != null) {
    			txInfo.restoreThreadLocalStatus();
    		}
    	}

202309162319459116.png
至此,回滚处理基本讲完了,接下去看成功完成提交的部分commitTransactionAfterReturning

TransactionAspectSupport的commitTransactionAfterReturning提交事务

调用事务管理器的提交方法。

    	protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
    		if (txInfo != null && txInfo.getTransactionStatus() != null) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
    			}
    			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    		}
    	}

AbstractPlatformTransactionManager的commit提交事务

这里就是前面我说了,就算没有异常,但是提交的时候也可能会回滚,因为有内层事务可能会标记回滚。所以这里先判断是否状态是否需要本地回滚,也就是设置回滚标记为全局回滚,不会进行回滚,再判断是否需要全局回滚,就是真的执行回滚。但是这里如果是发现有全局回滚,还要进行提交,就会报异常。

    	@Override
    	public final void commit(TransactionStatus status) throws TransactionException {
    		if (status.isCompleted()) {
    			throw new IllegalTransactionStateException(
    					"Transaction is already completed - do not call commit or rollback more than once per transaction");
    		}
    
    		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
    		if (defStatus.isLocalRollbackOnly()) {//当前事务状态需要回滚
    			if (defStatus.isDebug()) {
    				logger.debug("Transactional code has requested rollback");
    			}
    			processRollback(defStatus, false);//不可预期的回滚
    			return;
    		}
    		//设置了全局回滚
    		if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
    			if (defStatus.isDebug()) {
    				logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
    			}
    			processRollback(defStatus, true);//可预期的回滚,可能会报异常
    			return;
    		}
    		//处理提交
    		processCommit(defStatus);
    	}

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文