一、概述
SpringBoot的启动流程入下图所示,它主要分为加载主启动类和解析启动类两个部分,我将从这两个部分分别开始介绍。
二、加载主启动类
首先点入SpringApplication.run方法
之后进入SpringApplication.prepareContext方法
之后进入SpringApplication.applyInitializers方法
再返回SpringApplication.prepareContext方法进入load(context, sources.toArray(new Object[0]));方法。
之后进入BeanDefinitionLoader.load方法。
再进入AnnotatedBeanDefinitionReader.register方法并经过AnnotatedBeanDefinitionReader.doRegisterBean最后进入BeanDefinitionReaderUtils.registerBeanDefinition方法,将解析的BeanDefinition注册进入容器。
三、解析启动类
通过AbstractApplicationContext.refresh方法进入AbstractApplicationContext.invokeBeanFactoryPostProcessors方法
之后进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法。
之后进入SharedMetadataReaderFactoryContextInitializer.postProcessBeanDefinitionRegistry方法,这里将自动装配的类放到了容器当中。
再回到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,最后转到
ConfigurationClassPostProcessor.postProcessBeanFactory方法。
之后进入 ConfigurationClassPostProcessor.processConfigBeanDefinitions方法。
之后进入ConfigurationClassParser.parse方法
进入ConfigurationClassParser.processConfigurationClass方法。
之后进入ConfigurationClassParser.doProcessConfigurationClass方法。
先处理 @ComponentScans注解。
再通过ConfigurationClassParser.getImports方法,最后进入ConfigurationClassParser.collectImports进行@Import注解处理。
之后通过sourceClass.getAnnotationAttributes(Import.class.getName(), "value")这段代码获取注解上的信息。
回到ConfigurationClassParser.parse方法,改方法最后一行调用了DeferredImportSelectorHandler.process方法
往下走会调用DeferredImportSelectorHandler.processGroupImports方法。
之后进入 DeferredImportSelectorGrouping.getImports方法。
再通过DeferredImportSelectorGrouping.getImports方法进入AutoConfigurationGroup.process方法,这个方法是自动装配的重点方法。
getAutoConfigurationEntry 方法详细解释一下
/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 通过 SpringFactoriesLoader 类提供的方法加载类路径中的 META-INF 目录下的
// spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 对获得的注册配置类集合进行去重处理,防止多个项目引入同样的配置类
configurations = removeDuplicates(configurations);
// 获得注解中被 exclude 或 excludeName 所排除的类的集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 检查被排除类是否可实例化,是否被自动注册配置所使用,不符合条件则抛出异常
checkExcludedClasses(configurations, exclusions);
// 从自动配置类集合中去除被排除的类
configurations.removeAll(exclusions);
// 检查配置类的注解是否符合 spring.factories 文件中 AutoConfigurationImportFilter 指定的注解检查条件
configurations = getConfigurationClassFilter().filter(configurations);
// 将筛选完成的配置类和排查的配置类构建为事件类,并传入监听器。监听器的配置在于 spring.factories 文件中
// 通过 AutoConfigurationImportListener 指定
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
能够发现getCandidateConfigurations 方法中会通过 SpringFactoriesLoader 类来加载类路径中的 META-INF 目录下的 spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类。
下面是Spring Boot 自动装配源码 Debug 主线,感兴趣可以自行跟一下源码。
参考文章:
SpringBoot自动装配源码分析_spring自动装配源码解读_莫得感情的面包的博客-CSDN博客
https://www.cnblogs.com/Acaak/p/16932981.html
springboot之自动装配源码分析_springboot自动装配源码_平头 Brother的博客-CSDN博客
玩转 Spring Boot 原理篇(自动装配源码剖析)