Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析
基于最新Spring 5.x,详细介绍了Spring 事务源码,包括< tx:annotation-driven/>标签源码解析。
此前我们已经学习了Spring的<tx:advice/>事务标签源码解析:Spring 事务源码(1)—<tx:advice/>事务标签源码解析。现在我们来学习<tx:annotation-driven/>
事务标签的解析源码。
<tx:annotation-driven/>
标签用于开启注解事务支持,也就是说如果配置了该标签,那么可以使用基于注解的声明式事务!
<tx:annotation-driven/>
标签由org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser
这个解析器来单独解析,该解析器的uml类图如下,比较简单:
同样,我们主要看它的parse方法!
Spring 事务源码 系列文章
Spring 5.x 源码汇总
Spring 事务源码(1)—<tx:advice/>事务标签源码解析
Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析
Spring 事务源码(3)—@EnableTransactionManagement事务注解源码解析
Spring 事务源码(4)—BeanFactoryTransactionAttributeSourceAdvisor注解事务通知器源码解析
Spring 事务源码(5)—TransactionInterceptor事务拦截器与事务的AOP增强实现
Spring 事务源码(6)—createTransactionIfNecessary处理事务属性并尝试创建事务【两万字】
Spring 事务源码(7)—事务的completeTransactionAfterThrowing回滚、commitTransactionAfterReturning提交以及事务源码总结【一万字】
文章目录
- Spring 事务源码 系列文章
- 1 parse解析< tx:annotation-driven/>标签
- 1.1 registerTransactionalEventListenerFactory注册事务事件监听器工厂
- 1.2 configureAutoProxyCreator配置自动代理创建者
- 1.2.1 registerAutoProxyCreatorIfNecessary注册自动代理创建者
- 2 小结
1 parse解析< tx:annotation-driven/>标签
解析<tx:annotation-driven/>
标签。将在必要时调用AopNamespaceUtils#registerAutoProxyCreatorIfNecessary
方法,尝试向容器中注册一个InfrastructureAdvisorAutoProxyCreator
类型的bean定义。
/*** AnnotationDrivenBeanDefinitionParser的方法* <p>* 解析<tx:annotation-driven/>标签* 将在必要时调用AopNamespaceUtils#registerAutoProxyCreatorIfNecessary方法* 尝试向容器中注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator。*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {/** 注册事务事件监听器工厂TransactionalEventListenerFactory的bean定义* 用于解析@TransactionalEventListener注解方法为一个ApplicationListenerMethodTransactionalAdapter监听器*/registerTransactionalEventListenerFactory(parserContext);//获取<tx:annotation-driven/>标签的mode属性//该属性用于指示应该采用Spring AOP来对异步方法进行动态代理,还是采用AspectJ来进行静态织入//默认为proxy,即Spring AOP代理,如果设置为aspectj,那么还需要spring-aspects.jar(其内部包含了aspectjweaver依赖)。String mode = element.getAttribute("mode");//aspectj的mode处理,一般不需要考虑if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {registerJtaTransactionAspect(element, parserContext);}} else {// mode="proxy"//正常情况下的逻辑//尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者//并且配置AOP事务相关的一些基础bean定义,比如事务通知器、事务拦截器、事务属性源AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;
}
1.1 registerTransactionalEventListenerFactory注册事务事件监听器工厂
注册TransactionalEventListenerFactory
的bean定义,名为“org.springframework.transaction.config.internalTransactionalEventListenerFactory”
。该工厂可以将@TransactionalEventListener注解方法
解析为一个ApplicationListenerMethodTransactionalAdapter类型的事件监听器,用于支持事务事件的监听。
/**1. AnnotationDrivenBeanDefinitionParser的方法2. <p>3. 注册TransactionalEventListenerFactory的bean定义*/
private void registerTransactionalEventListenerFactory(ParserContext parserContext) {//创建bean定义RootBeanDefinition def = new RootBeanDefinition();//设置为TransactionalEventListenerFactory类型def.setBeanClass(TransactionalEventListenerFactory.class);//注册bean定义到beanFactory中,beanName为"org.springframework.transaction.config.internalTransactionalEventListenerFactory"parserContext.registerBeanComponent(new BeanComponentDefinition(def,TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME));
}
1.2 configureAutoProxyCreator配置自动代理创建者
configureAutoProxyCreator方法是内部类AopAutoProxyConfigurer的方法,该方法有两个目的:
- 尝试注册一个
InfrastructureAdvisorAutoProxyCreator
类型的自动代理创建者,用于创建代理对象。 - 配置AOP事务相关的一些基础bean定义,比如配置
BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源、TransactionInterceptor事务拦截器
等。
事务通知器的beanName为org.springframework.transaction.config.internalTransactionAdvisor
,并且全局只有一个,只有当容器中不存在该bean时才会继续解析当前<tx:annotation-driven/>
标签。因此,即使配置文件中存在多个<tx:annotation-driven/>
标签,仍然只会有一个标签的配置生效。
/*** AnnotationDrivenBeanDefinitionParser的内部类* <p>* 尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者* 并且配置AOP事务相关的一些基础bean定义,比如事务通知器、事务拦截器、事务属性源*/
private static class AopAutoProxyConfigurer {/*** 配置自动代理创建者*/public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {/** 如有必要,注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator* 并且配置proxy-target-class与expose-proxy属性*/AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);//获取事务通知器的banName,默认就是"org.springframework.transaction.config.internalTransactionAdvisor"String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;/** 如果目前不包含该名称的bean,那么将会注册一个BeanFactoryTransactionAttributeSourceAdvisor类型的注解专用事务通知器* 并且配置TransactionInterceptor事务拦截器以及AnnotationTransactionAttributeSource注解事务属性源的bean定义** 这里能够看出,即使可能存在多个<tx:annotation-driven/>标签,仍然只会有一个标签的配置生效*/if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);// 创建一个bean定义,class为"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"//就是一个适用于注解的事务属性源RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//注册事物属性源到容器中并且返回beanNameString sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);//创建TransactionInterceptor事务拦截器的bean定义RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);/** 注册事务管理器到事务拦截器中* 实际上就是设置TransactionInterceptor的transactionManagerBeanName属性指向一个事务管理器的bean*/registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));//注册拦截器到容器中并且返回beanNameString interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// Create the TransactionAttributeSourceAdvisor definition./** 创建一个TransactionAttributeSourceAdvisor的bean定义* 实际类型为BeanFactoryTransactionAttributeSourceAdvisor,就是一个事务通知器*/RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//设置transactionAttributeSource属性,就是AnnotationTransactionAttributeSource事务属性源advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));//设置adviceBeanName属性,就是TransactionInterceptor事务拦截器advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);//设置事务通知器的order属性if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}//将当前事务通知器的bean定义注册到容器中,name为"org.springframework.transaction.config.internalTransactionAdvisor"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. AnnotationDrivenBeanDefinitionParser的方法2. <p>3. 注册事务管理器到事务拦截器中4. 5. @param element <tx:annotation-driven/>标签元素6. @param def 事务拦截器的bean定义*/
private static void registerTransactionManager(Element element, BeanDefinition def) {//通过TxNamespaceHandler.getTransactionManagerName来获取事务管理器的beanName//将会解析<tx:annotation-driven/>标签的transaction-manager属性,默认值同样是transactionManagerdef.getPropertyValues().add("transactionManagerBeanName",TxNamespaceHandler.getTransactionManagerName(element));
}
1.2.1 registerAutoProxyCreatorIfNecessary注册自动代理创建者
如有必要,注册一个InfrastructureAdvisorAutoProxyCreator
类型的AutoProxyCreator
。该方法的源码与我们在此前的Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】的文章中讲过的registerAspectJAutoProxyCreatorIfNecessary方法基本一致。只不过AutoProxyCreator的类型变成了InfrastructureAdvisorAutoProxyCreator。
该方法分为三步,我们在此前已经讲过具体的源码了,在此不再赘述:
- 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary,尝试注册一个名为"org.springframework.aop.config.internalAutoProxyCreator",类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义。
- 调用useClassProxyingIfNecessary,解析proxy-target-class与expose-proxy属性。
- 调用registerComponentIfNecessary注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中。
/*** AopNamespaceUtils的方法* <p>* 如有必要,注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator* <p>* 该方法的源码与我们在此前的<aop:config/>标签解析部分讲过的registerAspectJAutoProxyCreatorIfNecessary方法基本一致* 只不过AutoProxyCreator的类型变成了InfrastructureAdvisorAutoProxyCreator*/
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {/** 1 尝试注册或者升级一个名为"org.springframework.aop.config.internalAutoProxyCreator"* 类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义*/BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));/** 2 解析proxy-target-class与expose-proxy属性* proxy-target-class用于设置代理模式,默认是优先JDK动态代理,其次CGLIB代理,可以指定为CGLIB代理* expose-proxy用于暴露代理对象,主要用来解决同一个目标类的方法互相调用时代理不生效的问题*/useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);/** 3 注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中*/registerComponentIfNecessary(beanDefinition, parserContext);
}/**1. AopConfigUtils的方法2. <p>3. 注册/升级自动代理创建者为InfrastructureAdvisorAutoProxyCreator类型*/
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {/** 注册/升级自动代理创建者为InfrastructureAdvisorAutoProxyCreator类型* 这个方法我们在此前的<aop:config/>标签解析部分也讲过了*/return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
2 小结
<tx:annotation-driven/>
标签用于开启注解事务支持,也就是说如果配置了该标签,那么可以使用基于注解的声明式事务!
从源码中能看出,该标签会:
- 尝试向容器注册名为org.springframework.transaction.config.internalTransactionalEventListenerFactory的
TransactionalEventListenerFactory类型的事务事件监听器工厂
的bean定义,该bean用于解析@TransactionalEventListener注解方法为一个ApplicationListenerMethodTransactionalAdapter监听器。 - 还会尝试注册一个名为org.springframework.aop.config.internalAutoProxyCreator的
InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者
的bean定义,该bean用于创建代理对象。但是该beanName的bean定义在容器中全局只会注册一个,并且有优先级,这一点我们在此前Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】的文章中就讲过了。 - 还会尝试
配置AOP事务相关的一些基础bean定义
,比如配置BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源(专门用于解析事务注解)
、TransactionInterceptor事务拦截器等。
总体来说,源码比较简单!当然前提是在我们理解了Spring AOP的源码之后才能得出这样的结论。
相关文章:
https://spring.io/
Spring Framework 5.x 学习
Spring Framework 5.x 源码
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析相关推荐
- 基于python3写的源码剖析_基于python3生成标签云代码解析
这篇文章主要介绍了基于python3生成标签云代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 标签云是现在大数据里面最喜欢使用的一种展现方式 ...
- springboot事务回滚源码_Spring Boot中的事务是如何实现的
1. 概述 一直在用SpringBoot中的@Transactional来做事务管理,但是很少想过SpringBoot是如何实现事务管理的,今天从源码入手,看看@Transactional是如何实现事 ...
- java基础巩固-宇宙第一AiYWM:为了维持生计,Spring全家桶_Part1-3(学学Spring源码呗:默认的标签和自定义标签是咋解析的)~整起
Part3:上一次说到了Spring的DefaultBeanDefinitionDocumentReader类中的parseBeanDefinitions(Element root, BeanDefi ...
- 事务回滚什么意思 try_分布式事务 TCC-Transaction 源码分析——事务恢复
1. 概述 本文分享 TCC 恢复.主要涉及如下二个 package 路径下的类: org.mengyun.tcctransaction.recover RecoverConfig,事务恢复配置接口 ...
- spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)
1. 声明式事务管理分类 声明式事务管理也有两种常用的方式, 一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解. 显然基于注解的方式更简单易用,更清爽. ...
- 【Spring】IOC:基于注解的IOC容器初始化源码分析
从 Spring2.0 以后的版本中,Spring 也引入了基于注解(Annotation)方式的配置,注解(Annotation)是 JDK1.5 中引入的一个新特性,用于简化 Bean 的配置,可 ...
- Spring 注解面面通 之 @CrossOrigin 注册处理方法源码解析
参照<Spring 注解面面通 之 @RequestMapping 注册处理方法源码解析>,其讲解了@RequestMapping注释的处理方法注册过程,而@CrossOrigin是基 ...
- Spring Cloud 微服务开发:入门、进阶与源码剖析 —— 2.2 Spring Cloud Eureka 进阶
2.2 Spring Cloud Eureka 进阶 上面一节介绍了服务发现以及Eureka的由来,同时展示了Eureka的最基础的搭建以及使用,包括Eureka Server和Eureka Clie ...
- Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)
前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...
最新文章
- Activity中的任务和返回站
- .NET 5.0预览版6发布:支持Windows ARM64设备
- 简单英文题 26 The Nearest Number(python)
- HttpServletResponse说明
- 对称加密、非对称加密深度解析
- Oracle多表联查时,某个字段由逗号分割的字符串组成,关系是此字符串切割后,对应另一张表某个字段,如何实现一条sql完成查询?
- WIN8系统中 任务管理器 性能栏 显示CPU利用率(已暂停)怎么回事?
- JS 创建对象方法
- 通过bat文件一键配置电脑IP
- 14.荔枝派 zero(全志V3S)-驱动OV2640拍照、录制视频
- BUUCTF笔记之Web系列部分WriteUp(三)
- 基于屏幕空间渲染的液体模拟
- (Vulnhub练习)-- fristileaks渗透实战
- 联通云图片上传官方文档
- 系统的认识大数据人工智能数据分析中的数据
- STM32F427主控(大疆A板)+K210视觉处理
- 分答项目_知识点:如何获取jquery选择器生成的input元素数组中的每个input元素的值?
- jdk32位安装包下载_神灯地图大数据采集工具破解版2020|神灯地图大数据采集软件 V4.6.0 官方版 下载_当下软件园...
- 人工智能新标准丨Whale 帷幄参与制定,助力信息安全产业建设
- Oracle DG日常运维命令大全