当前位置: 首页 > news >正文

Spring IOC 源码学习 声明式事务的入口点

一、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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://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);}@Overridepublic void init() {//  <tx:advice> 标签解析器:负责解析XML <tx:advice> 事务标签配置 TxAdviceBeanDefinitionParserregisterBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());//  <tx:annotation-driven> 标签解析器:负责解析注解相关的事务配置 AnnotationDrivenBeanDefinitionParserregisterBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());// JTA 规范的分布式事务管理器(管理跨多个资源的事务) TODOregisterBeanDefinitionParser("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@Nullablepublic 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 {@Transactionalpublic 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.*/@Overrideprotected 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;}}

Spring 声明式事务的入口点

http://www.jsqmd.com/news/508135/

相关文章:

  • 旧iOS设备优化工具:让你的旧iPhone/iPad重获新生的完整指南
  • Qwen3.5-9B多模态能力实战:从app.py启动到生产环境API封装完整指南
  • 51单片机智能小车避障功能实战:从红外模块到超声波测距完整配置
  • 告别繁琐编辑!超级文档全新上线「PDF转Word」功能,办公效率再升级
  • SUPER COLORIZER在软件测试中的应用:自动化验证图像上色质量
  • Lychee Rerank多任务学习实践:联合优化相关度与新颖性
  • PETRV2-BEV模型训练避坑指南:星图AI平台环境配置详解
  • zookeeper基础应用与实战
  • Qwen3-32B GPU算力提效方案:RTX4090D上FlashAttention-2加速推理实测提升300%
  • Firebase Studio 即将关闭:迁移指南与替代方案
  • 别再只怪网络了!排查Moonlight/SteamLink串流失败的另一个关键:Windows会话状态
  • 学术投稿管理2.0:Elsevier Tracker如何重构科研工作流
  • 通义千问3-4B优化升级:如何让本地知识库响应更快、更准确
  • 从零开始:使用Emotion2Vec+ Large搭建个人语音情绪日记应用
  • 粗硬发质必看!4款宝藏发胶实测,告别炸毛+钢丝头,新手闭眼冲 - 品牌测评鉴赏家
  • LoRA训练助手+VMware虚拟机:安全隔离的训练环境搭建
  • 水墨江南模型Ubuntu 20.04系统部署详解:从环境准备到服务上线
  • 2026干皮男士的素颜救星,都在这里了! - 品牌测评鉴赏家
  • Cogito-V1-Preview-Llama-3B安全部署指南:防范提示词注入与数据泄露
  • 腾讯HunyuanVideo-Foley音效生成:5分钟为视频添加电影级音效(保姆级教程)
  • Android 字体字重设置:从XML到Kotlin的奇妙之旅
  • 从零到一:基于STM32的自动量程电压表开发全流程解析
  • G-Helper免费快速上手:5分钟掌握华硕笔记本性能优化完整指南
  • CentOS 7.9双网卡实战:公网访问与内网数据库隔离配置指南
  • 发胶大揭秘!这些宝藏发胶你知道几个? - 品牌测评鉴赏家
  • SPSS Modeler缺失值处理实战:从数据审核到自动插补的完整流程
  • Qwen3-ASR-1.7B真实体验:方言识别、会议记录效果惊艳
  • Midscene低代码实战:5分钟搞定Android自动化测试(附WPS登录案例)
  • 告别接缝与色差:深度解析ArcGIS中7种镶嵌运算符,让你的TIF影像合成更完美
  • OpenCore Legacy Patcher终极解决方案:让老旧Mac焕发新生的实战指南