总结:

  • 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理(在处理@ComponentScan 自己所写@Component的类后)
  • 处理过程中会调用SpringFactoriesLoader#loadFactoryNames(),去查找所有jar下面META-INF/spring.factories中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
  • ConfigurationClassPostProcessor#processConfigBeanDefinitions()中loadBeanDefinitions对TransactionAutoConfiguration进行BeanDefinition的加载,并注册IOC容器

TransactionAutoConfiguration的BeanDefinition加载解析

调用链:

AbstractApplicationContext#refresh() --> AbstractApplicationContext#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors() --> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()--> ConfigurationClassPostProcessor#processConfigBeanDefinitions() --> ConfigurationClassPostProcessor#parse() --> ConfigurationClassParser#process() --> ConfigurationClassParser$DeferredImportSelectorGroupingHandler#processGroupImports() --> ConfigurationClassParser#processImports() --> ConfigurationClassParser#processConfigurationClass() --> ConfigurationClassParser#doProcessConfigurationClass()

ConfigurationClassParser#parse() 对延迟ImportSelector进行处理

private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();

public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectorHandler.process();
}

调用DeferredImportSelectorGroupingHandler#processGroupImports()

public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
// 给ConfigurationClassParser.groupings赋值
deferredImports.forEach(handler::register);
// DeferredImportSelectorGroupingHandler处理
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}

主要handler.processGroupImports()中 grouping.getImports()会查找出所有ConfigurationClassParser$DeferredImportSelectorGroupingHandler中的imports

public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
}
}
}

ConfigurationClassParser$DeferredImportSelectorGroupingHandler#getImports()

public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}

会调用AutoConfigurationImportSelector#process()

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}

会调用AutoConfigurationImportSelector#getAutoConfigurationEntry()

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
......
return new AutoConfigurationEntry(configurations, exclusions);
}

其中AutoConfigurationImportSelector#getCandidateConfigurations()会查找所有jar下面META-INF/spring.factories,进行loadFactoryNames。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
return configurations;
}

SpringFactoriesLoader#loadFactoryNames()

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
......
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

SpringFactoriesLoader#loadSpringFactories()

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {

	result = new HashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
} return result;
}

其中spring-boot-autoconfigure-XX.jar下面META-INF/spring.factories文件中就有:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

附:其中ConfigurationClassParser.groupings赋值,是在ConfigurationClassParser#register()执行的

public void register(DeferredImportSelectorHolder deferredImport) {
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}

loadBeanDefinitions

this.reader.loadBeanDefinitions(configClasses)进行BeanDefinition的加载,并注册到IOC容器

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
this.reader.loadBeanDefinitions(configClasses);
}

Spring源码之事务(一)— TransactionAutoConfiguration自动配置的更多相关文章

  1. 源码学习系列之SpringBoot自动配置(篇一)

    源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...

  2. 源码学习系列之SpringBoot自动配置(篇二)

    源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...

  3. SpringBoot源码学习系列之SpringMVC自动配置

    目录 1.ContentNegotiatingViewResolver 2.静态资源 3.自动注册 Converter, GenericConverter, and Formatter beans. ...

  4. SpringBoot源码学习系列之异常处理自动配置

    SpringBoot源码学习系列之异常处理自动配置 1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postm ...

  5. spring源码解析--事务篇(前篇)

    对于每一个JAVA程序员,spring应该是再熟悉不过的框架了,它的功能有多强大我就不多说了,既然他有这么强大的功能,是如何实现的呢?这个就需要从他的原理去了解,而最直接了解原理的方式莫过于源码.当然 ...

  6. spring源码分析---事务篇

    上一篇我介绍了spring事务的传播特性和隔离级别,以及事务定义的先关接口和类的关系.我们知晓了用TransactionTemplate(或者直接用底层P的latformTransactionMana ...

  7. SpringBoot源码学习系列之Locale自动配置

    目录 1.spring.messages.cache-duration 2.LocaleResolver 的方法名必须为localeResolver 3.默认LocaleResolver 4.指定默认 ...

  8. Spring源码阅读笔记03:xml配置读取

    前面的文章介绍了IOC的概念,Spring提供的bean容器即是对这一思想的具体实现,在接下来的几篇文章会侧重于探究这一bean容器是如何实现的.在此之前,先用一段话概括一下bean容器的基本工作原理 ...

  9. Spring源码深度解析之事务

    Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...

随机推荐

  1. 加密sqlite3数据库文件

    目录 EncryptSqlite3 实现原理 使用方法 不足之处 GitHub地址 EncryptSqlite3 加密sqlite3数据库,产生的数据库文件别人打不开. 实现原理 在写入文件前对每个字 ...

  2. 旋转子段 (思维stl)

    题目: 大概意思就是给你一个序列,你可以选择一段区间使它左右翻折一遍,然后呢,从1到n找一遍,看a[i]==i的数最多是多少. 其实刚才我已经把暴力思路说出来了,枚举每一个区间长度,枚举每一个左端点, ...

  3. [转]CSS学习笔记

    原文:http://www.fx114.net/qa-266-93710.aspx 01.什么是CSS.    CSS指层叠样式表(Cascading Style Sheets).    ·样式定义如 ...

  4. 【机器学习 Azure Machine Learning】使用Aure虚拟机搭建Jupyter notebook环境,为Machine Learning做准备(Ubuntu 18.04,Linux)

    问题描述 在Azure的VM中已经安装好Jupyter,并且通过jupyter notebook --port 9999 已经启动,但是通过本机浏览器,访问VM的公网IP,则始终是不能访问的错误.(T ...

  5. C#语言下使用gRPC、protobuf(Google Protocol Buffers)实现文件传输

    初识gRPC还是一位做JAVA的同事在项目中用到了它,为了C#的客户端程序和java的服务器程序进行通信和数据交换,当时还是对方编译成C#,我直接调用. 后来,自己下来做了C#版本gRPC编写,搜了很 ...

  6. chrome浏览器中调试窗口位置修改

    在这里修改就好了

  7. GO用内置包写爬虫

    一.要点 爬虫被想太多,把他当做一个模拟别人的请求响应即可了,所有呢go写爬虫关键是写请求 二.get请求 package main import ( "bytes" " ...

  8. slf4j -->log4j --> logback -->log4j2

    slf4j是一个接口:log4j\logback\log4j2是slf4j接口的持续更新的日志框架实现类:按照面向接口编程,java中导入slf4j最好,可以持续更新日志框架实现类. 详细情况见链接 ...

  9. Postman测试数据

    一.新增 在controller中编写新增的方法,加上@RequestBody注解,以json格式获取数据 在Postman中,有两种方法新增数据 直接新增参数,如: 以json格式新增 二.删除 根 ...

  10. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...