SpringBoot 启动流程

public static ConfigurableApplicationContext run(Class<?>[]primarySources,String[]args){
        // 两件事:1、初始化SpringApplication 2、执行run方法
        return new SpringApplication(primarySources).run(args);
}

初始化SpringApplication

  1. 读取SpringBootMyTestApplication类的所有信息
  2. 推断当前SpringBoot应用类型是 WebApplicationType.SERVLET 还是 WebApplicationType.REACTIVE
  3. 初始化classpathMETA-INF/spring.factories 中已配置得 ApplicationContextInitializer
  4. 初始化classpath下所有已配置得 ApplicationListener
  5. 根据调用栈,推断出 main 方法得类名

如何根据调用栈判断得?
还没找到判断方式,源码太难理解

执行run方法

  1. 初始化classpathMETA-INF/spring.factories 中已配置得 SpringApplicationRunListener
  2. 构建应用上下文
  • 获取初始化SpringApplication时配置的WebApplicationType

  • 配置 environment 系统环境,配置configureProfiles激活文件

      public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
    
  • 获取systemEnvironment配置的系统变量SystemEnvironmentPropertySource替换成OriginAwareSystemEnvironmentPropertySource,
    ConfigFileApplicationListener加载项目配置文件的监听器,获取配置文件

  1. 初始化上下文
    创建 AnnotationConfigServletWebServerApplicationContext Context上下文时,IOC容器也进行了创建,IOC容器的本质就是org.springframework.beans.factory.support.DefalutListableBeanFactory

  2. 刷新应用上下文的准备阶段

注册bean的流程

Spring容器在启动的时候,会将类解析成Spring内部的beanDefinition,并将beanDefinition存储到org.springframework.beans.factory.support.DefalutListableBeanFactory的Map中

((DefaultListableBeanFactory)((AnnotationConfigServletWebServerApplicationContext)context).beanFactory).beanDefinitionMap

下面就是一个启动类Bean的详细信息

springBootMyTestApplication -> {AnnotatedGenericBeanDefinition@4533}
"Generic bean: class [com.example.springbootmytest.SpringBootMyTestApplication]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null"

SpringBoot自动化配置原理?

  1. 刷新上下文(Ioc容器初始化过程的三个步骤)

(1)、Resource定位

(2)、BeanDefinition的载入

(3)、注册BeanDefinition

如何解析包含 @ComponentScan @Import 等等?

刷新BeanFactory,获取ConfigurableListableBeanFactory注册Bean的工厂
org.springframework.beans.factory.config.ConfigurableListableBeanFactory.java
postProcessBeanDefinitionRegistry

判断ConfigurableListableBeanFactory是否是BeanDefinitionRegistry的子类,ConfigurableListableBeanFactory强转成BeanDefinitionRegistry

BeanDefinitionRegistry中获取BeanDefinition,将BeanDefinitionRegistry获取到的BeanDefinition加载到List<BeanDefinitionHolder>

判断BeanDefinitionRegistry是否是SingletonBeanRegistry的子类 -> 将 BeanDefinitionRegistry强转成SingletonBeanRegistry

随后将List<BeanDefinitionHolder>转换成Set<BeanDefinitionHolder>

解析Set<BeanDefinitionHolder>,判断BeanDefinitionHolder是否是AnnotatedBeanDefinition的子类 -> 将 BeanDefinitionHolder强转成AnnotatedBeanDefinition,并获取Metadata,即为AnnotationMetadata

AnnotationMetadata初始化为ConfigurationClass,从ConfigurationClass获取的Metadata作为SourceClass去解析

org.springframework.context.annotation.ConfigurationClassParserdoProcessConfigurationClass

判断类中是否包含@Component@PropertySources@ComponentScan@Import

本次学习的SpringBoot源码版本为Spring-Boot-2.2.9.RELEASE

具体代码阅读笔记可以参考:https://github.com/lzmvlog/Spring-Boot-2.2.9.RELEASE/tree/main/spring-boot-mytest