惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
T
Threatpost
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - Franky
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
S
Security Affairs
P
Proofpoint News Feed
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
S
Security @ Cisco Blogs
H
Hacker News: Front Page
Security Archives - TechRepublic
Security Archives - TechRepublic
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
Know Your Adversary
Know Your Adversary
Y
Y Combinator Blog
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
量子位
博客园_首页
The Last Watchdog
The Last Watchdog
D
DataBreaches.Net
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
The Register - Security
The Register - Security
Schneier on Security
Schneier on Security
H
Help Net Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
L
Lohrmann on Cybersecurity
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
Cloudbric
Cloudbric
Microsoft Security Blog
Microsoft Security Blog

博客园 - daidaidaiyu

ZooKeepper 一文入门 ThingsBoard 规则链系统源码分析和自定义定时器 嵌入式开发入门知识 一文入门和实践Kafka 一文学习入门 ThingsBoard 开源物联网平台 Claude Code 使用一则 JMS, ActiveMQ 学习一则 Nacos实例一则及其源码环境搭建 一文学习 工作流开发 BPMN、 Flowable Spring IOC 源码学习 事务增强相关的对象创建 Spring IOC 源码学习 事务相关的 BeanDefinition 解析过程 (XML) GIS 核心知识 Spring IOC 源码学习 声明式事务的入口点 23.行为型 - 访问者模式 (Visitor Pattern) 一文学习 Spring AOP 源码全过程 22.行为型 - 迭代器模式 (Iterator Pattern) 21.行为型 - 状态模式 (State Pattern) Netty 核心知识 SpringCloud 微服务实现一则 (Eureka + Hystrix) 20.行为型 - 责任链模式(ChainofResponsibility Pattern) Modbus 协议 学习一则 - daidaidaiyu 19.行为型 - 策略模式(Strategy Pattern) - daidaidaiyu Redis 学习一则 - daidaidaiyu Android NDK 开发一则 - daidaidaiyu
一文学习 Spring 声明式事务源码全流程总结
daidaidaiyu · 2026-03-23 · via 博客园 - daidaidaiyu

Spring 声明式事务源码学习全过程

in short 四步走

  1. Srping 如何从配置中加载的入口
  2. Spring 声明式事务的相关的 BeanDefinition加载流程
  3. Spring 声明式事务的相关对象创建流程
  4. Spring 声明式事务的拦截调用的过程(包括: 方法嵌套, 事务传播属性的处理过程)

最后再看看第三方的框架是如何支持 Spring 声明式事务, 给Spring 托管事务的

一、Spring 声明式事务的入口点

对于XML入口点

XML配置定义

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/tx
		https://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/aop
		https://www.springframework.org/schema/aop/spring-aop.xsd">
	<tx:annotation-driven></tx:annotation-driven>

	<!-- dao bean-->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
		<property name="dataSource" ref = "dataSource"></property>
	</bean>

	<!-- service bean-->
	<bean id="bookService" class="org.yang.learn.spring.tx.BookService" >
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<!-- 数据源 bean-->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
		<property name="url"
				  value="jdbc:mysql://192.168.40.171:3306/workflow_test?serverTimezone=Asia/Shanghai&amp;characterEncoding=utf8&amp;useSSL=false"/>
		<property name="username" value="user_dev"></property>
		<property name="password" value="dev-sny.com"></property>
	</bean>
	<!-- 事务管理bean-->
	<bean id="transactionManager" class="org.springframework.jdbc.support.JdbcTransactionManager" >
		<constructor-arg ref="dataSource"></constructor-arg>
	</bean>
	<aop:config>
		<!--切点配置	-->
		<aop:pointcut id="serviceOperation"
					  expression="execution(* org.yang.learn.spring.tx.BookService.*(..))"/>
		<!-- 通知/增强 配置 (关键是这个通知指向 txAdvice '事务增强')-->
		<aop:advisor pointcut-ref="serviceOperation"  advice-ref="txAdvice"/>
	</aop:config>

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="insertWithTransaction" propagation="REQUIRED" />
			<tx:method name="insertWithNoTransaction" propagation="NEVER" />
		</tx:attributes>
	</tx:advice>
</beans>

在XML中配置 tx:.. 启用tx标签, 在解析XML自定义标签时, 会拿到 TxNamespaceHandler 命名空间处理器, 其主要工作就是注册事务相关的标签的解析器

  • tx:advice 标签解析器:负责XML相关的标签解析 TxAdviceBeanDefinitionParser
  • tx:annotation-driven 标签解析器:负责注解相关的解析 AnnotationDrivenBeanDefinitionPar

org.springframework.transaction.config.TxNamespaceHandler

public class TxNamespaceHandler extends NamespaceHandlerSupport {

	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";


	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}


	@Override
	public void init() {
		//  <tx:advice> 标签解析器:负责解析XML <tx:advice> 事务标签配置 TxAdviceBeanDefinitionParser
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		//  <tx:annotation-driven> 标签解析器:负责解析注解相关的事务配置 AnnotationDrivenBeanDefinitionParser
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		// JTA 规范的分布式事务管理器(管理跨多个资源的事务) TODO
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}
}

启用事务注解支持

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {

	/**
	 * Parses the {@code <tx:annotation-driven/>} tag. Will
	 * {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator}
	 * with the container as necessary.
	 */
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		if ("aspectj".equals(mode)) {
			// mode="aspectj"
			registerTransactionAspect(element, parserContext);
			if (ClassUtils.isPresent("jakarta.transaction.Transactional", getClass().getClassLoader())) {
				registerJtaTransactionAspect(element, parserContext);
			}
		}
		else {
			// 默认是  proxy 模式
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}
	

注册三剑客

/**
 * Inner class to just introduce an AOP framework dependency when actually in proxy mode.
 */
private static class AopAutoProxyConfigurer {

	public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

		String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
		if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
			Object eleSource = parserContext.extractSource(element);

			// Create the TransactionAttributeSource definition.
			RootBeanDefinition sourceDef = new RootBeanDefinition(
					"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
			sourceDef.setSource(eleSource);
			sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

			// Create the TransactionInterceptor definition.
			RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
			interceptorDef.setSource(eleSource);
			interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			registerTransactionManager(element, interceptorDef);
			interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
			String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

			/**
			 * 其中构建事务增强器(BeanFactoryTransactionAttributeSourceAdvisor)
			 * - **Pointcut(切点)**: 默认匹配所有标注 `@Transactional` 的类 / 方法(由 `TransactionAttributeSourcePointcut` 实现)
			 * - **Advice(通知)**: 即 `TransactionInterceptor`(事务拦截器)
			 * - **TransactionAttributeSource(注解解析器)**:即 `AnnotationTransactionAttributeSource`, 负责解析 `@Transactional` 注解的属性(传播行为、隔离级别等)。
			 */
			// Create the TransactionAttributeSourceAdvisor definition.
			RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
			advisorDef.setSource(eleSource);
			advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
			advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
			if (element.hasAttribute("order")) {
				advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
			}
			parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

			CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
			compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
			compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
			compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
			parserContext.registerComponent(compositeDef);
		}
	}
}

事务注解支持的三剑客

  1. AnnotationTransactionAttributeSource
    ↓(解析注解)
  2. TransactionInterceptor
    ↓(执行事务逻辑)
  3. BeanFactoryTransactionAttributeSourceAdvisor
    ↓(组装切点+通知)

总结一下XML入口, 就是无论 xml 支持 还是注解支持都会构造 org.springframework.transaction.interceptor.TransactionInterceptor 这个核心 advice 事务拦截器

对于注解的入口

@EnableTransactionManagement
public class TXMain {

	@Transactional
	public static void main(String[] args) throws Exception {
		System.out.println("==========================================================");
		//ApplicationContext context = new ClassPathXmlApplicationContext("application-tx.xml");
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TXMain.class);
		BookService bookService = context.getBean("bookService", BookService.class);
		Book book = new Book();
		book.setName("30秒精通javascript,一分钟精通java");
		book.setCode(""+System.currentTimeMillis());
//		bookService.insertWithTransaction(book );
		bookService.insertWithNoTransaction(book);
		System.out.println("bookService = "+bookService);
		System.out.println("bookService getList = "+bookService.getList());
		System.out.println("==========================================================");
	}
}

@EnableTransactionManagement 注解导入了 TransactionManagementConfigurationSelector 默认选中的是 ProxyTransactionManagementConfiguration

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * Returns {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
	 * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
	 * respectively.
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		return switch (adviceMode) {
		
			case PROXY -> new String[] {AutoProxyRegistrar.class.getName(),
					ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ -> new String[] {determineTransactionAspectClass()};
		};
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("jakarta.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

同样注解的三剑客

  1. AnnotationTransactionAttributeSource
    ↓(解析注解)
  2. TransactionInterceptor
    ↓(执行事务逻辑)
  3. BeanFactoryTransactionAttributeSourceAdvisor
    ↓(组装切点+通知)

org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration

/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.annotation;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.context.annotation.Role;
import org.springframework.transaction.config.TransactionManagementConfigUtils;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * {@code @Configuration} class that registers the Spring infrastructure beans
 * necessary to enable proxy-based annotation-driven transaction management.
 *
 * @author Chris Beams
 * @author Sebastien Deleuze
 * @since 3.1
 * @see EnableTransactionManagement
 * @see TransactionManagementConfigurationSelector
 */
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ImportRuntimeHints(TransactionRuntimeHints.class)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		// Accept protected @Transactional methods on CGLIB proxies, as of 6.0.
		return new AnnotationTransactionAttributeSource(false);
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

总结流程图

image

二、事务相关的 BeanDefinition 解析过程 (XML)

bean 标签

对于 jdbcTemplate transactionManager dataSource bookService 走的是默认命名空间的处理器, IOC标准解析流程, 不再啰嗦了
[[Spring IOC 源码学习 XML详细加载流程总结]]
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element ele) {//是否 是元素标签
				/**
				 * 处理默认命名空间的标签, 有如下四个
				 * <import></import>, <alias> </alias>, <bean></bean>, <beans></beans>
				 *
				 */
				if (delegate.isDefaultNamespace(ele)) {
					parseDefaultElement(ele, delegate);
				}
				else {
					/**
					 * 处理 非默认命名空间的标签;
					 * 	注意这里包括 <context:bean ...> <aop:xx ...> <tx:xx ...> 等等所有指定命名空间的xml配置
					 * 	主要逻辑是: 拿到元素的命名空间URI, 再从 XmlReaderContext 找到对应的 NamespaceHandler 调用解析 `parse`方法解析到 BeanDefinition 返回
					 */
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

aop 标签

对于 aop 部分的标签则的是 AOP 的流程

<aop:config>
	<!--切点配置	-->
	<aop:pointcut id="serviceOperation"
				  expression="execution(* org.yang.learn.spring.tx.BookService.*(..))"/>
	<!-- 通知/增强 配置 (关键是这个通知指向 txAdvice '事务增强')-->
	<aop:advisor pointcut-ref="serviceOperation"  advice-ref="txAdvice"/>
</aop:config>
  1. <aop:pointcut... : 解析为 org.springframework.aop.aspectj.AspectJExpressionPointcut 其 BeanDefinition
  2. <aop:advisor... : 解析为 org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor 其 BeanDefinition

internalAutoProxyCreator 的注册

[[Spring AOP 源码学习 详细流程总结]]

这里要注意AOP 的 ConfigBeanDefinitionParser 在解析时是会注册的一个internalAutoProxyCreator! (AOP解析流程, 在BPP回调时创建代理对象的)
org.springframework.aop.config.ConfigBeanDefinitionParser#parse

	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);

		/**
		 * 1. 注册一个名称为`org.springframework.aop.config.internalAutoProxyCreator` 对AOP处理的Bean Definition; 它是实现 InstantiationAwareBeanPostProcessor 接口的
		 * 名称是: org.springframework.aop.config.internalAutoProxyCreator
		 * 对应的类, 根据情况有以下三个可能: org.springframework.aop.config.AopConfigUtils#APC_PRIORITY_LIST
		 *	    InfrastructureAdvisorAutoProxyCreator.class,AspectJAwareAdvisorAutoProxyCreator.class, AnnotationAwareAspectJAutoProxyCreator.class
		 * 	注册一个名称为`org.springframework.aop.config.internalAutoProxyCreator` 对AOP处理的Bean Definition; 它是实现 InstantiationAwareBeanPostProcessor 接口的
		 *
		 */
		configureAutoProxyCreator(parserContext, element);

解析 <aop:pointcut>, <aop:advisor>, 没有切面标签
org.springframework.aop.config.ConfigBeanDefinitionParser#parse


	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);

		/**
		 * 1. 注册一个名称为`org.springframework.aop.config.internalAutoProxyCreator` 对AOP处理的Bean Definition; 它是实现 InstantiationAwareBeanPostProcessor 接口的
		 * 名称是: org.springframework.aop.config.internalAutoProxyCreator
		 * 对应的类, 根据情况有以下三个可能: org.springframework.aop.config.AopConfigUtils#APC_PRIORITY_LIST
		 *	    InfrastructureAdvisorAutoProxyCreator.class,AspectJAwareAdvisorAutoProxyCreator.class, AnnotationAwareAspectJAutoProxyCreator.class
		 * 	注册一个名称为`org.springframework.aop.config.internalAutoProxyCreator` 对AOP处理的Bean Definition; 它是实现 InstantiationAwareBeanPostProcessor 接口的
		 *
		 */
		configureAutoProxyCreator(parserContext, element);

		/**
		 * 2. 解析 <aop:config> 标签的子元素 (pointcut, advisor, aspect)
		 * 解析 <aspect ...>:
		 * 每一个通知(Advice) 都会封装为一个 AspectJPointcutAdvisor 的BeanDefinition 然后将其注册到 BeanFactory
		 *
		 *  AspectJPointcutAdvisor 的包含情况
		 * 每一个通知(Advice) 都会封装为一个 AspectJPointcutAdvisor(通知器) 类型的BeanDefinition 然后将其注册到 BeanFactory
		 * 	AspectJPointcutAdvisor 内部包含五种通知类类型:  AspectJAfterReturningAdvice AspectJAfterAdvice AspectJAroundAdvice AspectJMethodBeforeAdvice AspectJAfterThrowingAdvice
		 *  而每种通知类型的内部又主要有三个关键属性,包括:
		 *  1. java.lang.reflect.Method(通知切面的方法)
		 *	2. org.springframework.aop.aspectj.AspectJExpressionPointcut(切入点表达式)
		 * 	3. org.springframework.aop.aspectj.AspectInstanceFactory (切面实例工厂)
		 */
		List<Element> childElts = DomUtils.getChildElements(element);
		for (Element elt: childElts) {
			String localName = parserContext.getDelegate().getLocalName(elt);
			switch (localName) {
				/**
				 * 解析 pointcut/切入点  //筛选连接点, 即: 哪些方法需要被代理
				 * 解析为 org.springframework.aop.aspectj.AspectJExpressionPointcut 注册其 BeanDefinition
				 */
				case POINTCUT -> parsePointcut(elt, parserContext);
				/**
				 *  解析 advisor/通知/建议/增强处理  //即: 增强功能这一部分代码
				 * 解析为 org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor 注册其 BeanDefinition
				 */
				case ADVISOR -> parseAdvisor(elt, parserContext);
				/**
				
				 */
				case ASPECT -> parseAspect(elt, parserContext);
			}
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

tx 标签

前文说了由 org.springframework.transaction.config.TxAdviceBeanDefinitionParser 负责XML解析

先来到父类方法解析 TransactionInterceptor

org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal

/**
	 * Creates a {@link BeanDefinitionBuilder} instance for the
	 * {@link #getBeanClass bean Class} and passes it to the
	 * {@link #doParse} strategy method.
	 * @param element the element that is to be parsed into a single BeanDefinition
	 * @param parserContext the object encapsulating the current state of the parsing process
	 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element}
	 * @throws IllegalStateException if the bean {@link Class} returned from
	 * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null}
	 * @see #doParse
	 *
	 */
	@Override
	protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
		/**
		 *
		 * 1. 解析 <tx:advice ... 标签 封装为`GenericBeanDefinition`
		 * 其名称和class为org.springframework.transaction.interceptor.TransactionInterceptor
		 * 注意这个 TransactionInterceptor 实现了MethodInterceptor相当于是个Advice
		 *
		 * org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
		 * #parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
		 * org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal
		 *
		 *
		 */
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
		String parentName = getParentName(element);
		if (parentName != null) {
			builder.getRawBeanDefinition().setParentName(parentName);
		}
		Class<?> beanClass = getBeanClass(element);
		if (beanClass != null) {
			builder.getRawBeanDefinition().setBeanClass(beanClass);
		}
		else {
			String beanClassName = getBeanClassName(element);
			if (beanClassName != null) {
				builder.getRawBeanDefinition().setBeanClassName(beanClassName);
			}
		}
		builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
		BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
		if (containingBd != null) {
			// Inner bean definition must receive same scope as containing bean.
			builder.setScope(containingBd.getScope());
		}
		if (parserContext.isDefaultLazyInit()) {
			// Default-lazy-init applies to custom bean definitions as well.
			builder.setLazyInit(true);
		}
		doParse(element, parserContext, builder);
		return builder.getBeanDefinition();
	}

在回来解析到 transactionAttributeSource

org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse

@Override
	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
		/**
		 * 添加 transactionManager (事务管理)的 ref
		 */
		builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
		List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
		if (txAttributes.size() > 1) {
			parserContext.getReaderContext().error(
					"Element <attributes> is allowed at most once inside element <advice>", element);
		}
		else if (txAttributes.size() == 1) {
			/**
			 * 解析 <tx:attributes> ...  子标签
			 * 包括: 匹配的目标方法, 事务的传播属性, 是否只读..
			 * 类型是 `org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource`
			 */
			// Using attributes source.
			Element attributeSourceElement = txAttributes.get(0);
			RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
			builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
		}
		else {
			// Assume annotations source.
			builder.addPropertyValue("transactionAttributeSource",
					new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
		}
	}

汇总图

image

事务相关对象的BeanDefinition 对应AOP的三剑客

首先一点事务增强, 本质上就是AOP的逻辑, 在AOP最重要的就是AspectJPointcutAdvisor包含的三剑客
image

对应关系
image

可以看到少了AspectInstanceFactory 在事务这里的逻辑中不需它; 因为切面的逻辑是硬编码在TransactionInterceptor中了;

至此在事务相关的AOP对象已经齐了

三、事务增强 相关的对象创建

internalAutoProxyCreator 对象

首先是 internalAutoProxyCreator 它是负责创建AOP对象 它本身是BPP, 它会在 registerBeanPostProcessors(beanFactory); 过程中被实例化
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)


	/**
	 *  in short:
	 *  1. 拿到所有实现 BeanPostProcessor 的 bean, 然后进行分类存起来
	 *  这有一点, Spring 对 BeanDefinition 分成三种角色:
	 *  	1. 用户定义的 Bean (ROLE_APPLICATION)
	 *      2. 较复杂的 (ROLE_SUPPORT) 较复杂的? 通常是一个外部配置
	 *      3. Spring 内置的(ROLE_INFRASTRUCTURE)
	 *  2. 如果实现了 BeanPostProcessor 则会实例化这个bean, 但注意这里只是注册,并不会调用BeanPostProcessor的相关方法
	 *
	 *  另外 BeanPostProcessor 粗粒度太大, Spring 还细分一些子接口:
	 *  - SmartInstantiationAwareBeanPostProcessor 它提供了更高级的Bean实例化控制方法。主要作用在于允许对Bean的实例化过程进行更精细的控制和定制。
	 *  - MergedBeanDefinitionPostProcessor 在合并Bean定义(MergedBeanDefinition)之后但在实例化Bean之前,允许对合并后的Bean定义进行修改、调整或附加元数据。
	 *  - DestructionAwareBeanPostProcessor 它允许在Bean被销毁之前(例如,容器关闭或特定作用域的Bean销毁)执行一些操作。
	 */
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
		/**
		 * 拿到所有实现 BeanPostProcessor 的 bean名称
		 */
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		/**
		 * 计算 BeanPostProcessor(BPP) 的总数.
		 * +1 是什么操作? 原因是: 下一行,又加了一个 BeanPostProcessorChecker
		 */
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		// BeanPostProcessorChecker 这个BeanPostProcessor, 没啥实际作用, 就是记录了一些日志;
		beanFactory.addBeanPostProcessor(
				new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount));
		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		/**
		 * 对 BeanPostProcessor 进行分类存起来,  再调用, 每个集合分别是
		 * 1. priorityOrderedPostProcessors //有实现(PriorityOrdered)排序接口的
		 * 2. internalPostProcessors //Spring内部的bean, 见: Spring将bean分为三种角色
		 * 3. orderedPostProcessorNames //实现 Ordered 接口
		 * 4. nonOrderedPostProcessorNames //没有指定顺序, 无序的
		 */
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				/**
				 * 注意, 若 bean 实现了 PriorityOrdered 接口, 则会优先实例化它;
				 */
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		/**
		 * 注册所有常规BeanPostProcessors
		 * 这里 getBean 实例化bean !;
		 */
		// Now, register all regular(常规) BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		/**
		 * 最后, 注册所有 内置 BeanPostProcessor
		 */
		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		//最后再放一个 ApplicationListenerDetector 让它在最后 (不是重点, 见名应该是事件相关的)
		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

DefaultBeanFactoryPointcutAdvisor 和 AspectJExpressionPointcut 对象

internalAutoProxyCreator 会在 postProcessBeforeInstantiation 回调中的org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip判断时实例化所有的 Advisor

在实例化 Advisor 填充属性时也会把 AspectJExpressionPointcut 也实例化

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {

		/**
		 * 常规情况下:  这里只是检查下缓存和标记缓存
		 * 对于真正的AOP代理创建见:
		 * {@link AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)}
		 */
		Object cacheKey = getCacheKey(beanClass, beanName);
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {

			/**
			 *
			 *  不管需不需要, 只要处理过了就缓存
			 * 	advisedBeans 这个变量, 缓存所有处理过的 bean名称;
			 * 	value 为 boolean值, 如果为false 则不处理
			 */
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			/**
			 * isInfrastructureClass 是否是基础功能类,即 AOP相关的几个类:
			 * Advice.class Pointcut.class Advisor.class AopInfrastructureBean.class 都为true
			 *
			 * shouldSkip 判断时, 拿到容器的所有 Advisor, 并且实例化 `getBean()` 这个 Advisor
			 */
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

TransactionInterceptort 对象

是在 internalAutoProxyCreator 遇到需要增强代理的对象时, 这里是 bookService 去 getAdvicesAndAdvisorsForBean 查找到其匹配 bookService 的 Advisor
这里若 Advisor 匹配, 会调用 getAdvice 获取其切面, 此时切面不存在则会实例化它

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
		/**
		 * 拿到所有匹配织入当前bean的 所有通知器(Advisor)
		 * 做了三件事, 见: {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class, java.lang.String, org.springframework.aop.TargetSource)}
		 * 1. 往返回 `AspectJXXXAdvice`列表数组`0`索引 插入一个{@link org.springframework.aop.interceptor.ExposeInvocationInterceptor} 实例
		 * 方便传递参数用的
		 *
		 * 2. 怎么匹配(Advisor)?
		 * Advisor中的 `AspectJExpressionPointcut` 是实现 {@link ClassFilter} 和 {@link org.springframework.aop.MethodMatcher} 接口
		 * 一个进行类匹配, 一个进行方法匹配. Advisor 匹配会调用 getAdvice 获取其切面, 此时切面不存在则会实例化
		 *
		 * 3.  排序, 基于 `有向无环` 图进行排序; 可能匹配到多个切面(aspect)
		 *
		 */
		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			/**
			 *{@link org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#advisedBeans}
			 * 这个变量缓存所有处理过的 bean名称, value 为 boolean值, 如果为false 则不处理
			 */
			this.advisedBeans.put(cacheKey, Boolean.TRUE);//缓存, 表示已处理
			/**
			 * 创建代理
			 *
			 */
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

汇总图

image

四、事务增强 相关的方法调用流程

对于嵌套事务关键两个对象

首先梳理一下, 这里最复杂的问题是有多层方法嵌套的事务时, 对于事务的传播特性, 应该如何处理?
因为整个处理流程中涉及的对象非常多, 对于理解这里面的逻辑最为关键的对象有两个 TransactionStatus 和 TransactionInfo

TransactionInfo

该对象是在事务多层嵌套时流转的核心对象, 它几乎持有事务相关的所有对象
org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo

/**
 * Opaque object used to hold transaction information. Subclasses
 * must pass it back to methods on this class, but not see its internals.
 */
protected static final class TransactionInfo {

	// 1. 事务管理器(DataSource/JPA等事务管理器)
	private final PlatformTransactionManager transactionManager;

	// 2. 事务属性(传播行为、隔离级别、超时、只读等)
	private final TransactionAttribute transactionAttribute;

	// 3. 切入的目标方法名(用于日志、异常追踪)
	private final String joinpointIdentification;

	// 4. 真实的事务状态(Spring 事务核心状态对象)
	private TransactionStatus transactionStatus;

	// 5. 上一个事务信息(处理事务嵌套/挂起,形成链表)
	private TransactionInfo previousTransactionInfo;

	@Nullable
	private TransactionInfo oldTransactionInfo;

	public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
			@Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {

		this.transactionManager = transactionManager;
		this.transactionAttribute = transactionAttribute;
		this.joinpointIdentification = joinpointIdentification;
	}

	public PlatformTransactionManager getTransactionManager() {
		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
		return this.transactionManager;
	}

	@Nullable
	public TransactionAttribute getTransactionAttribute() {
		return this.transactionAttribute;
	}

	/**
	 * Return a String representation of this joinpoint (usually a Method call)
	 * for use in logging.
	 */
	public String getJoinpointIdentification() {
		return this.joinpointIdentification;
	}

	public void newTransactionStatus(@Nullable TransactionStatus status) {
		this.transactionStatus = status;
	}

	@Nullable
	public TransactionStatus getTransactionStatus() {
		return this.transactionStatus;
	}

	/**
	 * Return whether a transaction was created by this aspect,
	 * or whether we just have a placeholder to keep ThreadLocal stack integrity.
	 */
	public boolean hasTransaction() {
		return (this.transactionStatus != null);
	}

	private void bindToThread() {
		// Expose current TransactionStatus, preserving any existing TransactionStatus
		// for restoration after this transaction is complete.
		this.oldTransactionInfo = transactionInfoHolder.get();
		transactionInfoHolder.set(this);
	}

	private void restoreThreadLocalStatus() {
		// Use stack to restore old transaction TransactionInfo.
		// Will be null if none was set.
		transactionInfoHolder.set(this.oldTransactionInfo);
	}

	@Override
	public String toString() {
		return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction");
	}
}
// 1. 事务管理器(DataSource/JPA等事务管理器)
private final PlatformTransactionManager transactionManager;

// 2. 事务属性(传播行为、隔离级别、超时、只读等)
private final TransactionAttribute transactionAttribute;

// 3. 切入的目标方法名(用于日志、异常追踪)
private final String joinpointIdentification;

// 4. 真实的事务状态(Spring 事务核心状态对象)
private TransactionStatus transactionStatus;

// 5. 上一个事务信息(处理事务嵌套/挂起,形成链表)
private TransactionInfo previousTransactionInfo;

@Nullable
private TransactionInfo oldTransactionInfo;

记录了当前线程正在执行的事务所有关键信息,支撑事务的开启、挂起、恢复、提交 / 回滚全流程

对于这个状态对象关键的点是, 在多层嵌套时;
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

  • 在每次嵌套时都会调用 bindToThread
private void bindToThread() {
	// Expose current TransactionStatus, preserving any existing TransactionStatus
	// for restoration after this transaction is complete.
	this.oldTransactionInfo = transactionInfoHolder.get();
	transactionInfoHolder.set(this);
}

保存上一个 TransactionInfo

  • 在嵌套方法结束返回是调用 restoreThreadLocalStatus
private void restoreThreadLocalStatus() {
	// Use stack to restore old transaction TransactionInfo.
	// Will be null if none was set.
	transactionInfoHolder.set(this.oldTransactionInfo);
}

恢复上一个 TransactionInfo

TransactionStatus

org.springframework.transaction.TransactionStatus

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

	/**
	 * Return whether this transaction internally carries a savepoint,
	 * that is, has been created as nested transaction based on a savepoint.
	 * <p>This method is mainly here for diagnostic purposes, alongside
	 * {@link #isNewTransaction()}. For programmatic handling of custom
	 * savepoints, use the operations provided by {@link SavepointManager}.
	 * <p>The default implementation returns {@code false}.
	 * @see #isNewTransaction()
	 * @see #createSavepoint()
	 * @see #rollbackToSavepoint(Object)
	 * @see #releaseSavepoint(Object)
	 */
	default boolean hasSavepoint() {
		return false;
	}

	/**
	 * Flush the underlying session to the datastore, if applicable:
	 * for example, all affected Hibernate/JPA sessions.
	 * <p>This is effectively just a hint and may be a no-op if the underlying
	 * transaction manager does not have a flush concept. A flush signal may
	 * get applied to the primary resource or to transaction synchronizations,
	 * depending on the underlying resource.
	 * <p>The default implementation is empty, considering flush as a no-op.
	 */
	@Override
	default void flush() {
	}

}

大部分属性其实都在它的父类 TransactionExecution
org.springframework.transaction.TransactionExecution


package org.springframework.transaction;

/**
 * Common representation of the current state of a transaction.
 * Serves as base interface for {@link TransactionStatus} as well as
 * {@link ReactiveTransaction}, and as of 6.1 also as transaction
 * representation for {@link TransactionExecutionListener}.
 *
 * @author Juergen Hoeller
 * @since 5.2
 */
public interface TransactionExecution {

	/**
	 * Return the defined name of the transaction (possibly an empty String).
	 * <p>In case of Spring's declarative transactions, the exposed name will be
	 * the {@code fully-qualified class name + "." + method name} (by default).
	 * <p>The default implementation returns an empty String.
	 * @since 6.1
	 * @see TransactionDefinition#getName()
	 */
	default String getTransactionName() {
		return "";
	}

	/**
	 * Return whether there is an actual transaction active: this is meant to cover
	 * a new transaction as well as participation in an existing transaction, only
	 * returning {@code false} when not running in an actual transaction at all.
	 * <p>The default implementation returns {@code true}.
	 * @since 6.1
	 * @see #isNewTransaction()
	 * @see #isNested()
	 * @see #isReadOnly()
	 */
	default boolean hasTransaction() {
		return true;
	}

	/**
	 * Return whether the transaction manager considers the present transaction
	 * as new; otherwise participating in an existing transaction, or potentially
	 * not running in an actual transaction in the first place.
	 * <p>This is primarily here for transaction manager state handling.
	 * Prefer the use of {@link #hasTransaction()} for application purposes
	 * since this is usually semantically appropriate.
	 * <p>The "new" status can be transaction manager specific, e.g. returning
	 * {@code true} for an actual nested transaction but potentially {@code false}
	 * for a savepoint-based nested transaction scope if the savepoint management
	 * is explicitly exposed (such as on {@link TransactionStatus}). A combined
	 * check for any kind of nested execution is provided by {@link #isNested()}.
	 * <p>The default implementation returns {@code true}.
	 * @see #hasTransaction()
	 * @see #isNested()
	 * @see TransactionStatus#hasSavepoint()
	 */
	default boolean isNewTransaction() {
		return true;
	}

	/**
	 * Return if this transaction executes in a nested fashion within another.
	 * <p>The default implementation returns {@code false}.
	 * @since 6.1
	 * @see #hasTransaction()
	 * @see #isNewTransaction()
	 * @see TransactionDefinition#PROPAGATION_NESTED
	 */
	default boolean isNested() {
		return false;
	}

	/**
	 * Return if this transaction is defined as read-only transaction.
	 * <p>The default implementation returns {@code false}.
	 * @since 6.1
	 * @see TransactionDefinition#isReadOnly()
	 */
	default boolean isReadOnly() {
		return false;
	}

	/**
	 * Set the transaction rollback-only. This instructs the transaction manager
	 * that the only possible outcome of the transaction may be a rollback, as
	 * alternative to throwing an exception which would in turn trigger a rollback.
	 * <p>The default implementation throws an UnsupportedOperationException.
	 * @see #isRollbackOnly()
	 */
	default void setRollbackOnly() {
		throw new UnsupportedOperationException("setRollbackOnly not supported");
	}

	/**
	 * Return whether the transaction has been marked as rollback-only
	 * (either by the application or by the transaction infrastructure).
	 * <p>The default implementation returns {@code false}.
	 * @see #setRollbackOnly()
	 */
	default boolean isRollbackOnly() {
		return false;
	}

	/**
	 * Return whether this transaction is completed, that is,
	 * whether it has already been committed or rolled back.
	 * <p>The default implementation returns {@code false}.
	 */
	default boolean isCompleted() {
		return false;
	}

}

// 1. 是否是新事务
boolean isNewTransaction();

// 2. 是否标记为 只回滚
boolean isRollbackOnly();

// 3. 事务是否已完成(提交/回滚)
boolean isCompleted();

// 4. 是否是只读事务
boolean isReadOnly();

// 5. 是否被标记为 必须回滚
default boolean isRollbackOnly()

in short 可以理解为一个事务的状态: 是否是新事务, 是否是序列化, 是否是嵌套, 是否是只读的等

对于这个状态对象关键的点是, 在多层嵌套时, 主要在:
org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction
视情况(主要是根据事务的传播特性, 该方法也是处理多层事务的核心方法) 创建或修改事务状态中的属性

对于线程绑定事务管理对象 TransactionSynchronizationManager

org.springframework.transaction.support.TransactionSynchronizationManager

public abstract class TransactionSynchronizationManager {

	/**
	 * 线程私有事务资源
	 */
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");

	/**
	 * 事务同步?
	 */
	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");

	/**
	 * 当前事务的 名称
	 */
	private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<>("Current transaction name");
	/**
	 * 当前事务 是否只读
	 */
	private static final ThreadLocal<Boolean> currentTransactionReadOnly =
			new NamedThreadLocal<>("Current transaction read-only status");
	/**
	 * 当前事务的 隔离级别
	 */
	private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
			new NamedThreadLocal<>("Current transaction isolation level");
	/**
	 * 事务是否实际激活
	 */
	private static final ThreadLocal<Boolean> actualTransactionActive =
			new NamedThreadLocal<>("Actual transaction active");
			
	
	/**
	 * Retrieve a resource for the given key that is bound to the current thread.
	 * @param key the key to check (usually the resource factory)
	 * @return a value bound to the current thread (usually the active
	 * resource object), or {@code null} if none
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	@Nullable
	public static Object getResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		return doGetResource(actualKey);
	}
	/**
	 * Actually check the value of the resource that is bound for the given key.
	 */
	@Nullable
	private static Object doGetResource(Object actualKey) {
		Map<Object, Object> map = resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.get(actualKey);
		// Transparently remove ResourceHolder that was marked as void...
		if (value instanceof ResourceHolder resourceHolder && resourceHolder.isVoid()) {
			map.remove(actualKey);
			// Remove entire ThreadLocal if empty...
			if (map.isEmpty()) {
				resources.remove();
			}
			value = null;
		}
		return value;
	}
	
	/**
	 * Bind the given resource for the given key to the current thread.
	 * @param key the key to bind the value to (usually the resource factory)
	 * @param value the value to bind (usually the active resource object)
	 * @throws IllegalStateException if there is already a value bound to the thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static void bindResource(Object key, Object value) throws IllegalStateException {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Assert.notNull(value, "Value must not be null");
		Map<Object, Object> map = resources.get();
		// set ThreadLocal Map if none found
		if (map == null) {
			map = new HashMap<>();
			resources.set(map);
		}
		Object oldValue = map.put(actualKey, value);
		// Transparently suppress a ResourceHolder that was marked as void...
		if (oldValue instanceof ResourceHolder resourceHolder && resourceHolder.isVoid()) {
			oldValue = null;
		}
		if (oldValue != null) {
			throw new IllegalStateException(
					"Already value [" + oldValue + "] for key [" + actualKey + "] bound to thread");
		}
	}
	...........

可以看到有相当多的 ThreadLocal 变量, 它就是负责将事务信息与当前线程绑定的

绑定的源码逻辑
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

/**
 *
 * 真正在数据库中支持事务,
 * 1. 从数据源中获取链接
 * 2. 设置事务的隔离级别
 * 3. 关闭连接的自动提交
 * 4. 绑定连接到线程中 TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
 *
 * so , 如果想要复用或者是适配 Spring 的事务支持的数据库连接可以这么拿:
 * ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
 *
 */
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;

	try {
		/**
		 * 如果 ConnectionHolder 中没有数据库连接 则从数据源中获取,再存到[事务上下文] txObject对象中
		 * (真正的从数据源获取JDBC连接)
		 */
		if (!txObject.hasConnectionHolder() ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			Connection newCon = obtainDataSource().getConnection();
			if (logger.isDebugEnabled()) {
				logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
			}
			txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
		}
		txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
		con = txObject.getConnectionHolder().getConnection();
		/**
		 * 设置事务隔离级别
		 */
		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);
		txObject.setReadOnly(definition.isReadOnly());

		// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
		// so we don't want to do it unnecessarily (for example if we've explicitly
		// configured the connection pool to set it already).
		/**
		 * 关闭自动提交, 由 Spring 负责管理了
		 */
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}
		/**
		 * 判断是否 需要设置为只读事务
		 */
		prepareTransactionalConnection(con, definition);
		txObject.getConnectionHolder().setTransactionActive(true);

		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		/**
		 * 如果是新的连接 (也可以理解为新事务)
		 * 绑定到线程中
		 */
		// Bind the connection holder to the thread.
		if (txObject.isNewConnectionHolder()) {
			/**
			 * 将 ConnectionHolder 绑定到当前线程中 (ThreadLocal)
			 *
			 * 如果想要复用或者是适配 Spring 的事务支持可以这么拿:
			 * ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
			 * 数据库的连接
			 *
			 * > ConnectionHolder 可以理解为包装了数据库的连接, 不重要
			 */
			TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
		}
	}

	catch (Throwable ex) {
		if (txObject.isNewConnectionHolder()) {
			DataSourceUtils.releaseConnection(con, obtainDataSource());
			txObject.setConnectionHolder(null, false);
		}
		throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
	}
}

获取/复用的数据库连接的源码逻辑
org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction

@Override
	protected Object doGetTransaction() {
		/**
		 * 1. 创建一个DataSourceTransactionObject  封装对象, 可以理解为数据源上下文, 它包含:
		 * ConnectionHolder 数据库连接Holder对象
		 * newConnectionHolder : 是否是新连接 属性
		 * savepointAllowed: 是否允许'保存点'
		 * readOnly: 是否只读
		 *
		 */
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		//
		/**
		 * 设置允许'保存点'
		 */
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		/**
		 *  2. 从[事务同步管理器]中获取连接持有器, Holder 持有一个数据库连接, 如果是第一次获取则是 null
		 *  事务同步管理器: (TransactionSynchronizationManager): 该对象管理的资源都是绑定到当前事务中的; 内部使用的 ThreadLocal 存储的
		 *  如果没有事务, 第一次获取则是 null,
		 *  如果之前有事务, 将会获取的同一个 ConnectionHolder
		 *  将获取到的ConnectionHolder 存到 DataSourceTransactionObject
		 *
		 *  总之核心逻辑就是复用事务连接
		 */
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		/**
		 * 放到 事务上下文
		 */
		return txObject;
	}

重中之重的是: 的第三方扩展库/框架 都是通过这种方式支持Spring 声明式事务的, 见后文!

关键的源码流程

拦截器主流程入口

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

/**
	 * General delegate for around-advice-based subclasses, delegating to several other template
	 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
	 * as well as regular {@link PlatformTransactionManager} implementations and
	 * {@link ReactiveTransactionManager} implementations for reactive return types.
	 * @param method the Method being invoked
	 * @param targetClass the target class that we're invoking the method on
	 * @param invocation the callback to use for proceeding with the target invocation
	 * @return the return value of the method, if any
	 * @throws Throwable propagated from the target invocation
	 */
	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		/**
		 * 获取事务属性源
		 * 即: <tx:attributes> 标签配置的
		 */
		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		/**
		 * 1. 通过目标方法去匹配, 拿到对应的属性配置(TransactionAttribute), 比如: 是否只读, 事务传播属性, rollbackOn 等
		 */
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		/**
		 * 2. 拿到对应的事务管理器对象 (bean) TransactionManager
		 */
		final TransactionManager tm = determineTransactionManager(txAttr);

		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager rtm) {
			boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
			boolean hasSuspendingFlowReturnType = isSuspendingFunction &&
					COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
			if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
				throw new IllegalStateException("Coroutines invocation not supported: " + method);
			}
			CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);
			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
				Class<?> reactiveType =
						(isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
				if (adapter == null) {
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});
			InvocationCallback callback = invocation;
			if (corInv != null) {
				callback = () -> KotlinDelegate.invokeSuspendingFunction(method, corInv);
			}
			return txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, rtm);
		}

		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		/**
		 * 3. 生成获取到事务方法的唯一ID
		 */
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager cpptm)) {
			/**
			 * 4. 使用 TransactionManager 创建事务, 获取到事务信息对象 (TransactionInfo)
			 */
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				/**
				 * 5. 以事务执行调用, 回调方法
				 * retVal 是dao方法(原始方法) 执行的返回值
				 */
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				/**
				 * 6. 执行异常, 执行异常回滚操作
				 */
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);

				/**
				 * 注意这里还要再抛出去, 给外层事务知道 内层执行出现异常
				 */
				throw ex;
			}
			finally {
				/**
				 * 7. 不管异常与否, 清除当前线程的[事务上下文]信息
				 * 这个是在{@link org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary(org.springframework.transaction.PlatformTransactionManager, org.springframework.transaction.interceptor.TransactionAttribute, java.lang.String)}
				 * 中返回时 prepareTransactionInfo方法中,调用了 `txInfo.newTransactionStatus(status);` 保存到 ThreadLocal 中的
				 */
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && txAttr != null) {
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null) {
					if (retVal instanceof Future<?> future && future.isDone()) {
						try {
							future.get();
						}
						catch (ExecutionException ex) {
							if (txAttr.rollbackOn(ex.getCause())) {
								status.setRollbackOnly();
							}
						}
						catch (InterruptedException ex) {
							Thread.currentThread().interrupt();
						}
					}
					else if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
						// Set rollback-only in case of Vavr failure matching our rollback rules...
						retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
					}
				}
			}

			/**
			 * 8. 执行正常,执行正常提交处理
			 */
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
			
		.....
	}

创建 TransactionInfo

使用 TransactionManager 创建事务, 获取到事务的上下文对象 (TransactionInfo)

org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		/**
		 * 包装了一下事务源属性
		 */
		// If no name specified, apply method identification as transaction name.
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}
		/**
		 * 获取[事务状态]: 表示
		 * 是否 新事务
		 * 是否 有保存点
		 * 是否 只回滚
		 * 是否 完成
		 */
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				/**
				 *  1. 获取到一个封装对象: 可以理解为事务的状态
				 *  * 它包括: 是否只读, 是否允许'保存点', 从[事务同步管理器]获取 ConnectionHolder (注意第一次获取'无事务', Holder的connect是null的 );
				 *
				 *  2. 判断当前是否存在事务, 判断依据是 ConnectionHolder 内部 Active 标识符
				 *	 * 如果存在则, 处理事务传播特性
				 *   * {@link org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction(org.springframework.transaction.TransactionDefinition, java.lang.Object, boolean)}
				 *
				 *  3. 判断一下当前事务传播特性, 创建新的事务
				 * 	 * 在这里如果是 REQUIRED, REQUIRES_NEW, NESTED 传播特性, 才需要需要创建事务
				 *
				 *  4. 开始事务
				 * 	创建一个[事务状态]对象, 如果没有 数据库连接 则从数据源 中获取, 封装为 ConnectionHolder, 并赋值给[事务上下文]对象
				 * 	开始事务, 其实就是设置数据库连接的一些属性:
				 * 	  关闭自动提交, 由Spring 负责管理了
				 * 	  判断是否需要设置为只读事务
				 * 	  如果是新事务, 则绑定到当前线程中 (ThreadLocal)
				 *  org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction(org.springframework.transaction.TransactionDefinition, java.lang.Object, boolean, boolean, org.springframework.transaction.support.AbstractPlatformTransactionManager.SuspendedResourcesHolder)
				 *
				 * 见 {@link org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction(org.springframework.transaction.TransactionDefinition)}
				 */
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		/**
		 * 见: {@link org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo(org.springframework.transaction.PlatformTransactionManager, org.springframework.transaction.interceptor.TransactionAttribute, java.lang.String, org.springframework.transaction.TransactionStatus)}
		 */
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

获取事务

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

/**
	 * This implementation handles propagation behavior. Delegates to
	 * {@code doGetTransaction}, {@code isExistingTransaction}
	 * and {@code doBegin}.
	 * @see #doGetTransaction
	 * @see #isExistingTransaction
	 * @see #doBegin
	 */
	@Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		/**
		 * 将 TransactionStatus 和 事务方法唯一ID, 事务源属性 封装为 TransactionDefinition
		 */
		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

		/**
		 * 1. 获取到一个封装对象(DataSourceTransactionObject): 可以理解为事务上下文
		 * 它包括: 是否只读, 是否允许'保存点', 从[事务同步管理器]获取到的 ConnectionHolder (注意第一次'无事务'获取的 连接持有器Holder的connect是null的 );
		 *
		 * [事务同步管理器](TransactionSynchronizationManager): 该对象管理的资源都是绑定到当前事务中的; 内部使用ThreadLocal 存储的
		 * org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction()  设置允许'保存点'
		 */
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();

		/**
		 * 2. 判断当前是否存在事务, 判断依据是 ConnectionHolder 内部 Active 标识符
		 * 如果存在则, 处理事务传播特性
		 * org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction(org.springframework.transaction.TransactionDefinition, java.lang.Object, boolean)
		 */
		if (isExistingTransaction(transaction)) {
			/**
			 * 如果当前存在事务, 则走这个分支
			 */
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}
		/**
		 * 3. 判断一下当前事务传播特性, 创建新的事务
		 * 在这里如果是 REQUIRED, REQUIRES_NEW, NESTED 传播特性, 需要创建事务
		 */
		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			/**
			 * 挂起事务 (当前没有事务)
			 */
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
				/**
				 *  4. 开始事务
				 *   * 创建一个[事务状态]对象, 关键属性: 是否是新的、是否有保存点、是否只读、是否嵌套、是否为只回滚、是否完成。
				 *   * 如果没有 数据库连接 则从数据源 中获取, 封装为 ConnectionHolder, 并赋值给[事务上下文]对象
				 * 	  * 其实就是设置数据库连接的一些属性:
				 * 	  * 关闭自动提交, 由Spring 负责管理了
				 * 	  * 判断是否需要设置为只读事务
				 * 	  * 如果是新事务, 则通过 [事务同步资源管理器] TransactionSynchronizationManager 绑定到当前线程中 (ThreadLocal)
				 */
				return startTransaction(def, transaction, false, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}
在已有事务的情况-处理事务的传播特性

在已有事务的情况下, 主要是处理事务的传播特性
org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

/**
	 * Create a TransactionStatus for an existing transaction.
	 */
	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {
		/**
		 * 注意一点 , 现在是外部有事务的情况
		 * transaction 是txObject
		 */

		/**
		 * 1.如果是 NEVER (不允许事务) 传播特性, 则抛出异常
		 */
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}
		/**
		 * 2.如果是 NOT_SUPPORTED (不支持当前事务;总是以非事务的方式执行), 传播特性 挂起事务
		 */
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction");
			}
			//挂起事务
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			// 返回一个 无事务状态(TransactionStatus)
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
		}

		/**
		 * 3.如果是 REQUIRES_NEW 传播特性, 挂起当前事务
		 * 注意该特性:
		 * - 事务挂起后, 新的事务是完全独立的, 包括连接等等, 每个事务独立提交
		 * - 它的内层事务影响外层事务, 但是外层异常不影响内层事务
		 */
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction, creating new transaction with name [" +
						definition.getName() + "]");
			}

			/**
			 * 挂起当前事务, 何为挂起?
			 * 如果有事务的话
			 *  1. 将 DataSourceTransactionObject [事务上下文]中的 ConnectionHolder 设置为null
			 * 	2. 从[事务同步管理器]中解除绑定: TransactionSynchronizationManager.unbindResource(obtainDataSource())
			 * 	  这样就拿不到对象,不会对事务资源进行复用
			 * 	3. 挂起了, 下次还有恢复, 所以要保存被挂起的事务信息 (SuspendedResourcesHolder)
			 *
			 */
			SuspendedResourcesHolder suspendedResources = suspend(transaction);
			try {

				/**
				 *  //开启新的事务
				 */
				return startTransaction(definition, transaction, false, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}
		/**
		 * 4.如果是 NESTED (总是以嵌套的方式执行, 可以无限嵌套, MySQL的实现是 基于事务的保存点 savepoint )传播特性
		 */
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			if (!isNestedTransactionAllowed()) {
				throw new NestedTransactionNotSupportedException(
						"Transaction manager does not allow nested transactions by default - " +
						"specify 'nestedTransactionAllowed' property with value 'true'");
			}
			if (debugEnabled) {
				logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
			}
			/**
			 * 使用保存点, 对于NESTED的事务 (空实现,恒等于true)
			 */
			if (useSavepointForNestedTransaction()) {
				/**
				 * 4.1 创建一个新的[事务状态] DefaultTransactionStatus
				 */
				// Create savepoint within existing Spring-managed transaction,
				// through the SavepointManager API implemented by TransactionStatus.
				// Usually uses JDBC savepoints. Never activates Spring synchronization.
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, false, false, true, debugEnabled, null);
				this.transactionExecutionListeners.forEach(listener -> listener.beforeBegin(status));
				try {
					/**
					 * 4.2 创建保存点
					 * 最终是使用 ConnectionHolder 进行创建保存点, 底层是调用JDBC的接口方法 java.sql.Connection#setSavepoint(java.lang.String)
					 * org.springframework.jdbc.datasource.ConnectionHolder#createSavepoint()
					 */
					status.createAndHoldSavepoint();
				}
				catch (RuntimeException | Error ex) {
					this.transactionExecutionListeners.forEach(listener -> listener.afterBegin(status, ex));
					throw ex;
				}
				this.transactionExecutionListeners.forEach(listener -> listener.afterBegin(status, null));
				return status;
			}
			else {
				// Nested transaction through nested begin and commit/rollback calls.
				// Usually only for JTA: Spring synchronization might get activated here
				// in case of a pre-existing JTA transaction.
				return startTransaction(definition, transaction, true, debugEnabled, null);
			}
		}

		// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
		if (debugEnabled) {
			logger.debug("Participating in existing transaction");
		}
		if (isValidateExistingTransaction()) {
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
				Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] specifies isolation level which is incompatible with existing transaction: " +
							(currentIsolationLevel != null ?
									DefaultTransactionDefinition.getIsolationLevelName(currentIsolationLevel) :
									"(unknown)"));
				}
			}
			if (!definition.isReadOnly()) {
				if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] is not marked as read-only but existing transaction is");
				}
			}
		}
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}

无事务的情况-新建事务

org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction

/**
 * Start a new transaction.
 */
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
		boolean nested, boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

	/**
	 * 1. 创建一个[事务状态]对象
	 * 包括事务: 是否是新的、是否有保存点、是否只读、是否嵌套、是否为只回滚、是否完成。
	 */
	DefaultTransactionStatus status = newTransactionStatus(
			definition, transaction, true, newSynchronization, nested, debugEnabled, suspendedResources);
	this.transactionExecutionListeners.forEach(listener -> listener.beforeBegin(status));
	try {
		/**
		 * 2. 如果没有 数据库连接 则从数据源 中获取, 封装为 ConnectionHolder, 并赋值给[事务上下文]对象
		 * 设置数据库连的一些属性:
		 *  关闭自动提交, 由Spring 负责管理了
		 *  判断是否需要设置为只读事务
		 *  如果是新事务, 则绑定到当前线程中 (ThreadLocal)
		 *
		 *  {@link org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition)}
		 */
		doBegin(transaction, definition);
	}
	catch (RuntimeException | Error ex) {
		this.transactionExecutionListeners.forEach(listener -> listener.afterBegin(status, ex));
		throw ex;
	}
	prepareSynchronization(status, definition);
	this.transactionExecutionListeners.forEach(listener -> listener.afterBegin(status, null));
	return status;
}

事务方法执行异常情况

org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing

/**
	 * Handle a throwable, completing the transaction.
	 * We may commit or roll back, depending on the configuration.
	 * @param txInfo information about the current transaction
	 * @param ex throwable encountered
	 */
	protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
						"] after exception: " + ex);
			}
			/**
			 * 1. 匹配回滚的异常
			 *  txInfo.transactionAttribute.rollbackOn(ex) 匹配回滚的异常
			 */
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
				try {
					/**
					 * 2. 设置回滚状态
					 */
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
			}
			else {
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					throw ex2;
				}
			}
		}
	}

事务方法执行正常情况

org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning

	/**
	 * Execute after successful completion of call, but not after an exception was handled.
	 * Do nothing if we didn't create a transaction.
	 * @param txInfo information about the current transaction
	 */
	protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			/**
			 * 获取到当前的 TransactionStatus 提交到 TransactionManager
			 * 注意并不一定是数据库提交, 取决与 TransactionStatus 的状态实现, 有可能是回滚, 空提交
			 */
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
		}
	}

嵌套恢复线程中 TransactionInfo 信息

这个是在{@link org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary(org.springframework.transaction.PlatformTransactionManager, org.springframework.transaction.interceptor.TransactionAttribute, java.lang.String)}
中返回时 prepareTransactionInfo方法中,调用了 txInfo.newTransactionStatus(status); 保存到 ThreadLocal 中的

/**
 * Reset the TransactionInfo ThreadLocal.
 * <p>Call this in all cases: exception or normal return!
 * @param txInfo information about the current transaction (may be {@code null})
 */
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
	if (txInfo != null) {
		txInfo.restoreThreadLocalStatus();
	}
}

调用流程汇总图

image
https://img2024.cnblogs.com/blog/3723410/202603/3723410-20260323222541707-574711567.png

底层处理事务的源码

事务的开启

如果ConnectionHolder 中没有数据库连接 则从数据源中获取, (真正的从数据源获取JDBC连接), 关闭自动提交,绑定到线程
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

/**
 *
 * 真正在数据库中支持事务,
 * 1. 从数据源中获取链接
 * 2. 设置事务的隔离级别
 * 3. 关闭连接的自动提交
 * 4. 绑定连接到线程中 TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
 * so , 如果想要复用或者是适配 Spring 的事务支持的数据库连接可以这么拿:
 * ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
 *
 */
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;
	try {
		/**
		 * 如果ConnectionHolder 中没有数据库连接 则从数据源中获取,再存到[事务上下文]对象中
		 * (真正的从数据源获取JDBC连接)
		 */
		if (!txObject.hasConnectionHolder() ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			Connection newCon = obtainDataSource().getConnection();
			if (logger.isDebugEnabled()) {
				logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
			}
			txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
		}
		txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
		con = txObject.getConnectionHolder().getConnection();
		/**
		 * 设置事务隔离级别
		 */
		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);
		txObject.setReadOnly(definition.isReadOnly());

		// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
		// so we don't want to do it unnecessarily (for example if we've explicitly
		// configured the connection pool to set it already).
		/**
		 * 关闭自动提交, 由 Spring 负责管理了
		 */
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}
		/**
		 * 判断是否 需要设置为只读事务
		 */
		prepareTransactionalConnection(con, definition);
		txObject.getConnectionHolder().setTransactionActive(true);

		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		/**
		 * 如果是新的连接 (也可以理解为新事务)
		 */
		// Bind the connection holder to the thread.
		if (txObject.isNewConnectionHolder()) {
			/**  
			 * 将 ConnectionHolder 绑定到当前线程中 (ThreadLocal)  
			 * 下次再拿的话可以这么拿:  
			 * ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); * * > 可以理解 ConnectionHolder 包装了数据库的连接  
			 */
			TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
		}
	}

	catch (Throwable ex) {
		if (txObject.isNewConnectionHolder()) {
			DataSourceUtils.releaseConnection(con, obtainDataSource());
			txObject.setConnectionHolder(null, false);
		}
		throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
	}
}

事务的提交

判断一下 TransactionStatus 中状态, 决定是否要回滚
org.springframework.transaction.support.AbstractPlatformTransactionManager#commit


/**
 * This implementation of commit handles participating in existing
 * transactions and programmatic rollback requests.
 * Delegates to {@code isRollbackOnly}, {@code doCommit}
 * and {@code rollback}.
 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
 * @see #doCommit
 * @see #rollback
 */
@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;
	/**
	 * 1. 判断 [事务状态] 是否设置了回滚
	 */
	if (defStatus.isLocalRollbackOnly()) {
		if (defStatus.isDebug()) {
			logger.debug("Transactional code has requested rollback");
		}
		processRollback(defStatus, false);
		return;
	}
	/**
	 * 2. 判断 [事务状态] 是否设置了设置了全局回滚
	 * 这里会拿到 ConnectHolder 判断其回滚标记
	 */
	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;
	}
	/**
	 * 3. 处理提交
	 */
	processCommit(defStatus);
}

触发一些钩子, 只有是 最外层事务才真正的JDBC提交
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			boolean beforeCompletionInvoked = false;
			boolean commitListenerInvoked = false;

			try {
				boolean unexpectedRollback = false;
				//预留 hook方法
				prepareForCommit(status);

				triggerBeforeCommit(status);
				triggerBeforeCompletion(status);
				beforeCompletionInvoked = true;


				if (status.hasSavepoint()) {
					/**
					 * 1. 是否有事务保存点 (NESTED 才会有保存点)
					 * 有就释放保存点
					 */
					if (status.isDebug()) {
						logger.debug("Releasing transaction savepoint");
					}
					unexpectedRollback = status.isGlobalRollbackOnly();
					this.transactionExecutionListeners.forEach(listener -> listener.beforeCommit(status));
					commitListenerInvoked = true;
					status.releaseHeldSavepoint();
				}
				else if (status.isNewTransaction()) {
					/**
					 * 2. 是否是新事务, 即 是最外层事务才真正的JDBC提交
					 */
					if (status.isDebug()) {
						logger.debug("Initiating transaction commit");
					}
					unexpectedRollback = status.isGlobalRollbackOnly();
					this.transactionExecutionListeners.forEach(listener -> listener.beforeCommit(status));
					commitListenerInvoked = true;

					/**
					 * 真正的JDBC提交
					 */
					doCommit(status);
				}
				......

真正的 JDBC层提交
org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit

@Override  
protected void doCommit(DefaultTransactionStatus status) {  
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();  
    Connection con = txObject.getConnectionHolder().getConnection();  
    if (status.isDebug()) {  
       logger.debug("Committing JDBC transaction on Connection [" + con + "]");  
    }    try {  
       con.commit();  
    }    catch (SQLException ex) {  
       throw translateException("JDBC commit", ex);  
    }}

事务的回滚

跟提交同理, 只有最外层的才应该真正的提交
org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

/**
	 * Process an actual rollback.
	 * The completed flag has already been checked.
	 * @param status object representing the transaction
	 * @throws TransactionException in case of rollback failure
	 */
	private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
			boolean unexpectedRollback = unexpected;
			boolean rollbackListenerInvoked = false;
			try {
				/**
				 * 1. 如果事务状态有保存点, 将事务状态回滚到设置的保存点 (仅NESTED才会存在保存点)
				 */
				triggerBeforeCompletion(status);
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Rolling back transaction to savepoint");
					}
					this.transactionExecutionListeners.forEach(listener -> listener.beforeRollback(status));
					rollbackListenerInvoked = true;
					status.rollbackToHeldSavepoint();
				}
				else if (status.isNewTransaction()) {
					/**
					 * 2. 如果是新(外层)事务的话, 真正执行回滚 (只有在最外层是执行回滚的)
					 */
					if (status.isDebug()) {
						logger.debug("Initiating transaction rollback");
					}
					this.transactionExecutionListeners.forEach(listener -> listener.beforeRollback(status));
					rollbackListenerInvoked = true;
					/**
					 * 真正在数据库连接层 执行事务回滚
					 */
					doRollback(status);
				}
				else {
					// Participating in larger transaction
					if (status.hasTransaction()) {
						if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
							}
							/**
							 *  3. 设置 ConnectionHolder 中的 RollbackOnly 标记状态
							 */
							doSetRollbackOnly(status);
						}
						else {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
							}
						}
					}
					else {
						logger.debug("Should roll back transaction but cannot - no transaction available");
					}
					// Unexpected rollback only matters here if we're asked to fail early
					if (!isFailEarlyOnGlobalRollbackOnly()) {
						/**
						 * 4. 设置非预期的回滚标记
						 */
						unexpectedRollback = false;
					}
				}
			}
			catch (RuntimeException | Error ex) {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				if (rollbackListenerInvoked) {
					this.transactionExecutionListeners.forEach(listener -> listener.afterRollback(status, ex));
				}
				throw ex;
			}

			triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
			if (rollbackListenerInvoked) {
				this.transactionExecutionListeners.forEach(listener -> listener.afterRollback(status, null));
			}

			// Raise UnexpectedRollbackException if we had a global rollback-only marker
			if (unexpectedRollback) {
				throw new UnexpectedRollbackException(
						"Transaction rolled back because it has been marked as rollback-only");
			}
		}
		finally {
			/**
			 * 5. 清除当前事务信息, 注意, 这里如果有被挂起的事务还会恢复它
			 */
			cleanupAfterCompletion(status);
		}
	}

真正的 JDBC层回滚
org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback

	@Override
	protected void doRollback(DefaultTransactionStatus status) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
		Connection con = txObject.getConnectionHolder().getConnection();
		if (status.isDebug()) {
			logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
		}
		try {
			con.rollback();
		}
		catch (SQLException ex) {
			throw translateException("JDBC rollback", ex);
		}
	}

最后, 看看第三方框架是如何支持Spring声明式事务的

JdbcTemplate 是怎么支持Spring声明式事务的?

org.springframework.jdbc.core.JdbcTemplate
关键在于确保数据源中获取的 JDBC连接 都是同一个, 而在声明式事务配置中, 无论是 dataSource 对象, 还是 jdbcTemplate Bean 都没有被代理; 从配置上, 来看也完全没有关联

其实是 JdbcTemplate 在获取连接时 适配了 Spring 事务相关的代码, 关键源码:

  • org.springframework.jdbc.core.JdbcTemplate#execute(org.springframework.jdbc.core.CallableStatementCreator, org.springframework.jdbc.core.CallableStatementCallback<T>)
  • org.springframework.jdbc.datasource.DataSourceUtils#getConnection
  • org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
public static Connection doGetConnection(DataSource dataSource) throws SQLException {  
   Assert.notNull(dataSource, "No DataSource specified");  
	//从 TransactionSynchronizationManager 获取连接 (由Spring声明式事务处理的连接)
   ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);  
   if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {  
      conHolder.requested();  
      if (!conHolder.hasConnection()) {  
         logger.debug("Fetching resumed JDBC Connection from DataSource");  
         conHolder.setConnection(fetchConnection(dataSource));  
      }  
      return conHolder.getConnection();  
   }  
   // Else we either got no holder or an empty thread-bound holder here.  
   logger.debug("Fetching JDBC Connection from DataSource");  
   Connection con = fetchConnection(dataSource);
......

MyBatis 是怎么支持Spring声明式事务的?

org.mybatis.spring.transaction.SpringManagedTransaction

org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

/**
	 * Actually obtain a JDBC Connection from the given DataSource.
	 * Same as {@link #getConnection}, but throwing the original SQLException.
	 * <p>Is aware of a corresponding Connection bound to the current thread, for example
	 * when using {@link DataSourceTransactionManager}. Will bind a Connection to the thread
	 * if transaction synchronization is active (for example, if in a JTA transaction).
	 * <p>Directly accessed by {@link TransactionAwareDataSourceProxy}.
	 * @param dataSource the DataSource to obtain Connections from
	 * @return a JDBC Connection from the given DataSource
	 * @throws SQLException if thrown by JDBC methods
	 * @see #doReleaseConnection
	 */
	public static Connection doGetConnection(DataSource dataSource) throws SQLException {
		Assert.notNull(dataSource, "No DataSource specified");

		ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
		if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
			conHolder.requested();
			if (!conHolder.hasConnection()) {
				logger.debug("Fetching resumed JDBC Connection from DataSource");
				conHolder.setConnection(fetchConnection(dataSource));
			}
			return conHolder.getConnection();
		}
		// Else we either got no holder or an empty thread-bound holder here.

		logger.debug("Fetching JDBC Connection from DataSource");
		Connection con = fetchConnection(dataSource);

		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			try {
				// Use same Connection for further JDBC actions within the transaction.
				// Thread-bound object will get removed by synchronization at transaction completion.
				ConnectionHolder holderToUse = conHolder;
				if (holderToUse == null) {
					holderToUse = new ConnectionHolder(con);
				}
				else {
					holderToUse.setConnection(con);
				}
				holderToUse.requested();
				TransactionSynchronizationManager.registerSynchronization(
						new ConnectionSynchronization(holderToUse, dataSource));
				holderToUse.setSynchronizedWithTransaction(true);
				if (holderToUse != conHolder) {
					TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
				}
			}
			catch (RuntimeException ex) {
				// Unexpected exception from external delegation call -> close Connection and rethrow.
				releaseConnection(con, dataSource);
				throw ex;
			}
		}

		return con;
	}

Hibernate 是怎么支持Spring声明式事务的?

  1. 开启事务的源码
@Override
	protected void doBegin(Object transaction, TransactionDefinition definition) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

		if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			throw new IllegalTransactionStateException(
					"Pre-bound JDBC Connection found! HibernateTransactionManager does not support " +
					"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
					"It is recommended to use a single HibernateTransactionManager for all transactions " +
					"on a single DataSource, no matter whether Hibernate or JDBC access.");
		}

		SessionImplementor session = null;

		try {
			if (!txObject.hasSessionHolder() || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				Interceptor entityInterceptor = getEntityInterceptor();
				Session newSession = (entityInterceptor != null ?
						obtainSessionFactory().withOptions().interceptor(entityInterceptor).openSession() :
						obtainSessionFactory().openSession());
				if (this.sessionInitializer != null) {
					this.sessionInitializer.accept(newSession);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
				}
				txObject.setSession(newSession);
			}

			session = txObject.getSessionHolder().getSession().unwrap(SessionImplementor.class);

			boolean holdabilityNeeded = this.allowResultAccessAfterCompletion && !txObject.isNewSession();
			boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
			if (holdabilityNeeded || isolationLevelNeeded || definition.isReadOnly()) {
				if (this.prepareConnection && ConnectionReleaseMode.ON_CLOSE.equals(
						session.getJdbcCoordinator().getLogicalConnection().getConnectionHandlingMode().getReleaseMode())) {
					// We're allowed to change the transaction settings of the JDBC Connection.
					if (logger.isDebugEnabled()) {
						logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
					}
					Connection con = session.connection();
					Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
					txObject.setPreviousIsolationLevel(previousIsolationLevel);
					txObject.setReadOnly(definition.isReadOnly());
					if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
						int currentHoldability = con.getHoldability();
						if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
							txObject.setPreviousHoldability(currentHoldability);
							con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
						}
					}
					txObject.connectionPrepared();
				}
				else {
					// Not allowed to change the transaction settings of the JDBC Connection.
					if (isolationLevelNeeded) {
						// We should set a specific isolation level but are not allowed to...
						throw new InvalidIsolationLevelException(
								"HibernateTransactionManager is not allowed to support custom isolation levels: " +
								"make sure that its 'prepareConnection' flag is on (the default) and that the " +
								"Hibernate connection release mode is set to ON_CLOSE.");
					}
					if (logger.isDebugEnabled()) {
						logger.debug("Not preparing JDBC Connection of Hibernate Session [" + session + "]");
					}
				}
			}

			if (definition.isReadOnly() && txObject.isNewSession()) {
				// Just set to MANUAL in case of a new Session for this transaction.
				session.setHibernateFlushMode(FlushMode.MANUAL);
				// As of 5.1, we're also setting Hibernate's read-only entity mode by default.
				session.setDefaultReadOnly(true);
			}

			if (!definition.isReadOnly() && !txObject.isNewSession()) {
				// We need AUTO or COMMIT for a non-read-only transaction.
				FlushMode flushMode = session.getHibernateFlushMode();
				if (FlushMode.MANUAL.equals(flushMode)) {
					session.setHibernateFlushMode(FlushMode.AUTO);
					txObject.getSessionHolder().setPreviousFlushMode(flushMode);
				}
			}

			Transaction hibTx;

			// Register transaction timeout.
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
				// Applies to all statements, also to inserts, updates and deletes!
				hibTx = session.getTransaction();
				hibTx.setTimeout(timeout);
				hibTx.begin();
			}
			else {
				// Open a plain Hibernate transaction without specified timeout.
				hibTx = session.beginTransaction();
			}

			// Add the Hibernate transaction to the session holder.
			txObject.getSessionHolder().setTransaction(hibTx);

			// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
			if (getDataSource() != null) {
				ConnectionHolder conHolder = new ConnectionHolder(session::connection);
				if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
					conHolder.setTimeoutInSeconds(timeout);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Exposing Hibernate transaction as JDBC [" + conHolder.getConnectionHandle() + "]");
				}
				TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
				txObject.setConnectionHolder(conHolder);
			}
			// 绑定到线程
			// Bind the session holder to the thread.
			if (txObject.isNewSessionHolder()) {
				TransactionSynchronizationManager.bindResource(obtainSessionFactory(), txObject.getSessionHolder());
			}
			txObject.getSessionHolder().setSynchronizedWithTransaction(true);
		}

		catch (Throwable ex) {
			if (txObject.isNewSession()) {
				try {
					if (session != null && session.getTransaction().getStatus() == TransactionStatus.ACTIVE) {
						session.getTransaction().rollback();
					}
				}
				catch (Throwable ex2) {
					logger.debug("Could not rollback Session after failed transaction begin", ex);
				}
				finally {
					SessionFactoryUtils.closeSession(session);
					txObject.setSessionHolder(null);
				}
			}
			throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
		}
	}
  1. 复用的源码
    org.springframework.orm.hibernate5.SpringSessionContext#currentSession
/**
	 * Retrieve the Spring-managed Session for the current thread, if any.
	 */
	@Override
	public Session currentSession() throws HibernateException {
		Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
		if (value instanceof Session) {
			return (Session) value;
		}
		else if (value instanceof SessionHolder) {
			// HibernateTransactionManager
			SessionHolder sessionHolder = (SessionHolder) value;
			Session session = sessionHolder.getSession();
			if (!sessionHolder.isSynchronizedWithTransaction() &&
					TransactionSynchronizationManager.isSynchronizationActive()) {
				TransactionSynchronizationManager.registerSynchronization(
						new SpringSessionSynchronization(sessionHolder, this.sessionFactory, false));
				sessionHolder.setSynchronizedWithTransaction(true);
				// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
				// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
				FlushMode flushMode = session.getHibernateFlushMode();
				if (flushMode.equals(FlushMode.MANUAL) &&
						!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
					session.setHibernateFlushMode(FlushMode.AUTO);
					sessionHolder.setPreviousFlushMode(flushMode);
				}
			}
			return session;
		}
		else if (value instanceof EntityManagerHolder) {
			// JpaTransactionManager
			return ((EntityManagerHolder) value).getEntityManager().unwrap(Session.class);
		}

		if (this.transactionManager != null && this.jtaSessionContext != null) {
			try {
				if (this.transactionManager.getStatus() == Status.STATUS_ACTIVE) {
					Session session = this.jtaSessionContext.currentSession();
					if (TransactionSynchronizationManager.isSynchronizationActive()) {
						TransactionSynchronizationManager.registerSynchronization(
								new SpringFlushSynchronization(session));
					}
					return session;
				}
			}
			catch (SystemException ex) {
				throw new HibernateException("JTA TransactionManager found but status check failed", ex);
			}
		}

		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			Session session = this.sessionFactory.openSession();
			if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
				session.setHibernateFlushMode(FlushMode.MANUAL);
			}
			SessionHolder sessionHolder = new SessionHolder(session);
			TransactionSynchronizationManager.registerSynchronization(
					new SpringSessionSynchronization(sessionHolder, this.sessionFactory, true));
			TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
			sessionHolder.setSynchronizedWithTransaction(true);
			return session;
		}
		else {
			throw new HibernateException("Could not obtain transaction-synchronized Session for current thread");
		}
	}