【Spring Transaction afterCommit 调用不生效的原因分析】

news/2024/7/23 23:22:14 标签: spring, java, 后端

问题描述
service A 发送事件A1 提交成功之后 在afterCommit调用service B 发送事件B1 在afterCommit中未调用

环境
jdk8
spring-tx:4.3.29.RELEASE

源码调用链
TransactionInterceptor.invoke–>
TransactionAspectSupport.invokeWithinTransaction–>commitTransactionAfterReturning–>commitTransactionAfterReturning–>
AbstractPlatformTransactionManager.commit–>processCommit–>triggerAfterCommit

java">private void triggerAfterCommit(DefaultTransactionStatus status) {
		if (status.isNewSynchronization()) {
			if (status.isDebug()) {
				logger.trace("Triggering afterCommit synchronization");
			}
			TransactionSynchronizationUtils.triggerAfterCommit();
		}
	}


/**
	 * Return if a new transaction synchronization has been opened
	 * for this transaction.
	 */
	public boolean isNewSynchronization() {
		return this.newSynchronization;
	}

对于此场景 service B 发送事件B1后,status.isNewSynchronization() 为false 故不用再次调用

DefaultTransactionStatus属性newSynchronization的生成逻辑源码调用链
TransactionInterceptor.invoke–>
TransactionAspectSupport.invokeWithinTransaction–>createTransactionIfNecessary–>
AbstractPlatformTransactionManager.getTransaction

java">@Override
	public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
		Object transaction = doGetTransaction();

		// Cache debug flag to avoid repeated checks.
		boolean debugEnabled = logger.isDebugEnabled();

		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}

		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}

		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			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 ex) {
				resume(null, suspendedResources);
				throw ex;
			}
			catch (Error err) {
				resume(null, suspendedResources);
				throw err;
			}
		}
		else {
			// 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);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
		}
	}

如果transaction存在,则return handleExistingTransaction(definition, transaction, debugEnabled);
不存在,则新创建,如果新创建则newSynchronization为true


http://www.niftyadmin.cn/n/5262743.html

相关文章

STM32 LCD 简单显示彩色图片

STM32 LCD 数组方式简单显示彩色图片 文章目录 STM32 LCD 数组方式简单显示彩色图片前言1、图片处理1.1 准备图片1.2 查看和调整图片大小 2、Picture2Hex软件使用3、函数代码实现3、图片显示效果4、显示图片太大会报错总结 前言 在使用LCD填充的时候发现正点原子提供了一个很好…

MySQL数据库,视图、存储过程与存储函数

数据库对象&#xff1a; 常见的数据库对象&#xff1a; 视图&#xff1a; 视图是一种虚拟表&#xff0c;本身是不具有数据的占用很少的内存空间。 视图建立在已有表的基础上&#xff0c;视图赖以建立的这些表称为基表。 视图的创建和删除只影响视图本身&#xff0c;不影响对…

Axure的元件库的使用以及详细案例

目录 元件库的使用 元件介绍 元件的基本使用 矩形、按钮、标题的使用​编辑 图片的使用 图片以及热区的使用 表单元件的使用 表格元件的使用 登录界面 个人简介界面 元件库的使用 元件介绍 Axure提供了一套丰富的元件库&#xff0c;用于快速创建原型中常见的UI界面元素…

学习网址1

链接&#xff1a;https://www.zhihu.com/question/443690249/answer/2162390505 要说提升程序员自身能力的话&#xff0c;最推荐的就是国外的技术社区。缺点就是国内访问不方便。 国外技术社区 Stack Overflow https://stackoverflow.com/ 全球最活跃的程序员技术问答交流…

详细说说vuex

Vuex 是什么 Vuex有几个属性及作用注意事项vuex 使用举例Vuex3和Vuex4有哪些区别 创建 Store 的方式在组件中使用 Store辅助函数的用法响应式的改进Vuex4 支持多例模式 Vuex 是什么 Vuex是一个专门为Vue.js应用设计的状态管理构架&#xff0c;它统一管理和维护各个Vue组件的可…

P5719 【深基4.例3】分类平均

题目描述 给定 &#xfffd; n 和 &#xfffd; k&#xff0c;将从 1 到 &#xfffd; n 之间的所有正整数可以分为两类&#xff1a;A 类数可以被 &#xfffd; k 整除&#xff08;也就是说是 &#xfffd; k 的倍数&#xff09;&#xff0c;而 B 类数不能。请输出这两类数…

wsl发行版删除、安装和docker镜像压缩

1 删除wsl发行版/镜像 wsl -l -v查看已发行的发行版本 NAME STATE VERSION * docker-desktop-data Running 2docker-desktop Running 2Ubuntu-xx.xx Stopped 2 #前两个发行版就是你的docker-deskto…

web基础和面试题

基础知识 socket网络通信\TCP \HTTP协议 ARP地址解析协议&#xff1a;是根据IP地址获取物理地址的一个TCP/IP协议。 http协议和TCP协议的区别: 1、http协议是应用层的协议&#xff0c;TCP协议是传输层的协议&#xff0c;http协议是建立是TCP协议之上的&#xff0c;http是无状…