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

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
L
LINUX DO - 最新话题
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Secure Thoughts
S
Schneier on Security
MyScale Blog
MyScale Blog
月光博客
月光博客
U
Unit 42
www.infosecurity-magazine.com
www.infosecurity-magazine.com
AI
AI
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
爱范儿
爱范儿
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
Securelist
B
Blog RSS Feed
Spread Privacy
Spread Privacy
H
Help Net Security
Know Your Adversary
Know Your Adversary
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
V
V2EX
MongoDB | Blog
MongoDB | Blog
GbyAI
GbyAI
博客园 - 叶小钗
D
DataBreaches.Net
T
Troy Hunt's Blog
Project Zero
Project Zero
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
P
Privacy International News Feed
The Last Watchdog
The Last Watchdog
K
Kaspersky official blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Latest news
Latest news
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V2EX - 技术
V2EX - 技术
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs
T
Threatpost
O
OpenAI News
Recorded Future
Recorded Future
Help Net Security
Help Net Security
罗磊的独立博客

博客园 - daidaidaiyu

ZooKeepper 一文入门 ThingsBoard 规则链系统源码分析和自定义定时器 嵌入式开发入门知识 一文入门和实践Kafka 一文学习入门 ThingsBoard 开源物联网平台 Claude Code 使用一则 JMS, ActiveMQ 学习一则 Nacos实例一则及其源码环境搭建 一文学习 工作流开发 BPMN、 Flowable 一文学习 Spring 声明式事务源码全流程总结 Spring IOC 源码学习 事务增强相关的对象创建 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 IOC 源码学习 事务相关的 BeanDefinition 解析过程 (XML)
daidaidaiyu · 2026-03-21 · via 博客园 - daidaidaiyu

事务相关的 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对象已经齐了