基于最新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的方法,该方法有两个目的:

  1. 尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者,用于创建代理对象。
  2. 配置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。
该方法分为三步,我们在此前已经讲过具体的源码了,在此不再赘述:

  1. 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary,尝试注册一个名为"org.springframework.aop.config.internalAutoProxyCreator",类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义。
  2. 调用useClassProxyingIfNecessary,解析proxy-target-class与expose-proxy属性。
  3. 调用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/>标签用于开启注解事务支持,也就是说如果配置了该标签,那么可以使用基于注解的声明式事务!
  从源码中能看出,该标签会:

  1. 尝试向容器注册名为org.springframework.transaction.config.internalTransactionalEventListenerFactory的TransactionalEventListenerFactory类型的事务事件监听器工厂的bean定义,该bean用于解析@TransactionalEventListener注解方法为一个ApplicationListenerMethodTransactionalAdapter监听器。
  2. 还会尝试注册一个名为org.springframework.aop.config.internalAutoProxyCreator的InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者的bean定义,该bean用于创建代理对象。但是该beanName的bean定义在容器中全局只会注册一个,并且有优先级,这一点我们在此前Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】的文章中就讲过了。
  3. 还会尝试配置AOP事务相关的一些基础bean定义,比如配置BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源(专门用于解析事务注解)、TransactionInterceptor事务拦截器等。

  总体来说,源码比较简单!当然前提是在我们理解了Spring AOP的源码之后才能得出这样的结论。

相关文章:
  https://spring.io/
  Spring Framework 5.x 学习
  Spring Framework 5.x 源码

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析相关推荐

  1. 基于python3写的源码剖析_基于python3生成标签云代码解析

    这篇文章主要介绍了基于python3生成标签云代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 标签云是现在大数据里面最喜欢使用的一种展现方式 ...

  2. springboot事务回滚源码_Spring Boot中的事务是如何实现的

    1. 概述 一直在用SpringBoot中的@Transactional来做事务管理,但是很少想过SpringBoot是如何实现事务管理的,今天从源码入手,看看@Transactional是如何实现事 ...

  3. java基础巩固-宇宙第一AiYWM:为了维持生计,Spring全家桶_Part1-3(学学Spring源码呗:默认的标签和自定义标签是咋解析的)~整起

    Part3:上一次说到了Spring的DefaultBeanDefinitionDocumentReader类中的parseBeanDefinitions(Element root, BeanDefi ...

  4. 事务回滚什么意思 try_分布式事务 TCC-Transaction 源码分析——事务恢复

    1. 概述 本文分享 TCC 恢复.主要涉及如下二个 package 路径下的类: org.mengyun.tcctransaction.recover RecoverConfig,事务恢复配置接口 ...

  5. spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)

    1. 声明式事务管理分类 声明式事务管理也有两种常用的方式, 一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解. 显然基于注解的方式更简单易用,更清爽. ...

  6. 【Spring】IOC:基于注解的IOC容器初始化源码分析

    从 Spring2.0 以后的版本中,Spring 也引入了基于注解(Annotation)方式的配置,注解(Annotation)是 JDK1.5 中引入的一个新特性,用于简化 Bean 的配置,可 ...

  7. Spring 注解面面通 之 @CrossOrigin 注册处理方法源码解析

      参照<Spring 注解面面通 之 @RequestMapping 注册处理方法源码解析>,其讲解了@RequestMapping注释的处理方法注册过程,而@CrossOrigin是基 ...

  8. Spring Cloud 微服务开发:入门、进阶与源码剖析 —— 2.2 Spring Cloud Eureka 进阶

    2.2 Spring Cloud Eureka 进阶 上面一节介绍了服务发现以及Eureka的由来,同时展示了Eureka的最基础的搭建以及使用,包括Eureka Server和Eureka Clie ...

  9. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)

    前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...

最新文章

  1. Activity中的任务和返回站
  2. .NET 5.0预览版6发布:支持Windows ARM64设备
  3. 简单英文题 26 The Nearest Number(python)
  4. HttpServletResponse说明
  5. 对称加密、非对称加密深度解析
  6. Oracle多表联查时,某个字段由逗号分割的字符串组成,关系是此字符串切割后,对应另一张表某个字段,如何实现一条sql完成查询?
  7. WIN8系统中 任务管理器 性能栏 显示CPU利用率(已暂停)怎么回事?
  8. JS 创建对象方法
  9. 通过bat文件一键配置电脑IP
  10. 14.荔枝派 zero(全志V3S)-驱动OV2640拍照、录制视频
  11. BUUCTF笔记之Web系列部分WriteUp(三)
  12. 基于屏幕空间渲染的液体模拟
  13. (Vulnhub练习)-- fristileaks渗透实战
  14. 联通云图片上传官方文档
  15. 系统的认识大数据人工智能数据分析中的数据
  16. STM32F427主控(大疆A板)+K210视觉处理
  17. 分答项目_知识点:如何获取jquery选择器生成的input元素数组中的每个input元素的值?
  18. jdk32位安装包下载_神灯地图大数据采集工具破解版2020|神灯地图大数据采集软件 V4.6.0 官方版 下载_当下软件园...
  19. 人工智能新标准丨Whale 帷幄参与制定,助力信息安全产业建设
  20. Oracle DG日常运维命令大全

热门文章

  1. 基于51单片机简易智能家居
  2. java内嵌_Java内嵌类
  3. Tecplot 3602015
  4. MCAL-GTM之时钟管理CMU
  5. 异常:egret获取引擎列表失败
  6. 《敏捷革命》读书笔记
  7. 安卓9可用的性能监视器_监视应用程序生态系统的性能和可用性
  8. 穆易天气app代码(二)
  9. python获取页面隐藏元素_python之selenium操作隐藏元素
  10. Python批量查单词源码