SpringBoot 版本 2.7.1
SpringApplication在构造方法时,就会读取META-INF/spring.factories的类,缓存到SpringFactoriesLoader中(这是Spring的SPI),注意这里的缓存不仅仅只有org.springframework.boot.autoconfigure.EnableAutoConfiguration,包括文件中所有key-value


缓存是一个静态变量

SpringApplication第298行,通过SPI从META-INF/spring.factories获取org.springframework.boot.SpringApplicationRunListener的实现类并加载

通过构造器创建自定义RunListener实例

进入到自定义RunListener的构造方法

第299行,通过spring.factories获取的所有SpringApplicationRunListener的实现类,并调用start方法


SpringApplication第302行,创建spring环境配置类,默认环境变量实现类为ApplicationServletEnvironme
ApplicationServletEnvironment的抽象父类为AbstractEnvironment,他的成员变量MutablePropertySources propertySources是环境变量核心。包含了List

PropertySource类结构

继续回到ApplicationServletEnvironment的构造方法创建,在默认调用抽象父类的构造中,执行了customizePropertySources(MutablePropertySources propertySources)方法

这个方法由ApplicationServletEnvironment的直接父类StandardServletEnvironment来实现,添加了两个默认的propertySource,再去调用StandardServletEnvironment的直接父类StandardEnvironment的customizePropertySources(MutablePropertySources propertySources)方法。再添加两个默认的propertySource,这里就包含了系统配置System.getProperties()和系统运行环境System.getenv()

以上只是prepareEnvironment方法的第341行逻辑,341行之后,还会添加一些propertySource、调用省略SpringApplicationRunListener的environmentPrepared方法等

完成spring环境配置类创建
创建IOC核心ApplicationContext,第305行
context核心变量的核心包括:
a. List beanFactoryPostProcessors
b. ConfigurableEnvironment environment
c. DefaultListableBeanFactory beanFactory

默认ApplicationContext的实现类是AnnotationConfigServletWebServerApplicationContext

它的间接父类是GenericApplicationContext,构造方法中初始化了beanFactory,这里与spring的ClassPathXmlApplicationContext有区别,ClassPathXmlApplicationContext是在refresh执行时才创建beanFactory,而GenericApplicationContext是在refresh之前
以上为创建ApplicationContext逻辑。
进行ApplicationContext赋值处理,SpringApplication第307行prepareContext方法

进入prepareContext方法,这里赋值了environment、添加默认类到IOC容器(beanFactory的间接父类DefaultSingletonBeanRegistry中的singletonObjects,作为一级缓存)、设置循环依赖状态、添加默认BeanFactoryPostProcessor

调用SpringApplicationRunListener的contextPrepared、contextLoaded方法


SpringApplication第308行,核心方法refreshContext(context);

调用context.refresh(),由AnnotationConfigServletWebServerApplicationContext的间接抽象父类AbstractApplicationContext来实现。

这里的实现很简单,只是返回了beanFactory对象(如果context是用spring的ClassPathXmlApplicationContext,会在这里进行beanDefinition的构建,这里不做深入区别讨论)

Prepare the bean factory for use in this context.

会默认添加一些beanPostProcess实现(比如ApplicationContextAwareProcessor,用来判断bean是否实现了各种Aware接口,如果实现了,ApplicationContextAwareProcessor会在postProcessBeforeInitialization执行回调)。

会默认注册一些单例bean到ioc容器(比如 environment、systemProperties、systemEnvironment等)。DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry,里面的成员变量 Map

Allows post-processing of the bean factory in context subclasses.

由AnnotationConfigServletWebServerApplicationContext实现

super.postProcessBeanFactory(beanFactory)。会添加WebApplicationContextServletContextAwareProcessor到BeanPostProcessor

4. AbstractApplicationContext第564行,invokeBeanFactoryPostProcessors。
这个方法会执行springboot的自动装配核心逻辑
Invoke factory processors registered as beans in the context.


PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 方法
第112行invokeBeanDefinitionRegistryPostProcessors



进入ConfigurationClassPostProcessor.processConfigBeanDefinitions方法
从beanFactory的beanDefinitionMap中,目前beanDefinitionMap的数据只有初始化时候加入的,如下

接着第287行 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory),会依次遍历判断是否有@Configuration注解,启动类因为有@SpringBootApplication,它引用了@SpringBootConfiguration,而@SpringBootConfiguration又引用了@Configuration。把符合要求的BeanDefinition封装成BeanDefinitionHolder(第288行),然后加入到 List configCandidates 集合中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
通过过滤放这里configCandidates集合只有启动类

第327行
Set candidates = new LinkedHashSet<>(configCandidates);
332行
构建了一个
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);
processConfigBeanDefinitions方法第329-367行,递归遍历candidates集合,解析每一个BeanDefinitionHolder
第331行 parser.parse(candidates)

ConfigurationClassParser的parse方法,第175行

ConfigurationClassParser第206行,parse的重载方法

进入ConfigurationClassParser第225行,processConfigurationClass
第250行,开始处理@Configuration注解的类逻辑

进入ConfigurationClassParser,可以看到这里针对类上的注解做了很多判断,是否有@Component、@PropertySource、@ComponentScan、@Import注解等

先看ConfigurationClassParser-272行,当类上有@Component注解时,判断是否有内部类,再递归判断内部类是否有@Component


ConfigurationClassParser-第276行,判断是否有@PropertySources注解

ConfigurationClassParser-第442行开始,processPropertySource 方法
先判断@PropertySource的value是否为空(这是必要配置),然后加载value的值为Resource对象
ConfigurationClassParser-第463行,factory.createPropertySource(name, new EncodedResource(resource, encoding)),这里的factory默认是DefaultPropertySourceFactory

ConfigurationClassParser-第479行,进入DefaultPropertySourceFactory.createPropertySource方法

会创建并返回ResourcePropertySource对象
ResourcePropertySource的构造方法如下,通过getNameForResource(resource.getResource()) 和 *PropertiesLoaderUtils.loadProperties(resource)方法构造成 String name 和 Properties source,继续调用父类构造方法

最终ResourcePropertySource的顶层抽象类为PropertySource。构造完成后返回

回到ConfigurationClassParser-463行,将构造返回的propertySource,再调用addPropertySource(propertySource)*方法

ConfigurationClassParser-479行,addPropertySource方法
判断environment的propertySources是否已经包含了此propertySource,如果没有包含,添加到propertySources中
第505-510行,是用来判断插入propertySources的位置

回到ConfigurationClassParser-280行,处理完了@PropertySources的逻辑,继续往下
ConfigurationClassParser-289行,开始处理@ComponentScan逻辑,进入296行componentScanParser.parse

ComponentScanAnnotationParser-68行parse方法,初始化ClassPathBeanDefinitionScanner类,处理了basePackages的包扫描路径等

直接看到ComponentScanAnnotationParser-128行,ClassPathBeanDefinitionScanner scanner.doScan(StringUtils.toStringArray(basePackages));

进入ClassPathBeanDefinitionScanner-272行的doScan方法,入参为scanBasePackages的值
从275行开始,遍历所有basePackages,276行,从basePackage的值开始扫描符合要求的bean,并封装成BeanDefinition

由父类ClassPathScanningCandidateComponentProvider实现findCandidateComponents 方法,第311行
再进入316行 scanCandidateComponents(basePackage);

ClassPathScanningCandidateComponentProvider第416行开始
获取classpath下符合basePackage的 .class路径。如这里的: classpath:org/hopehomi/**/*.class

获取到该路径下所有的 *.class路径
