【SpringBoot】程序启动流程

基本的SpringBoot的应用程序,有两个重要元素:

  • 注解:@SpringBootApplication
  • 启动方法:SpringApplication.run(FirstBootApplication.class, args) ;

 1、@SpringBootApplication注解

 1 @Target(ElementType.TYPE)
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 @Inherited
 5 @SpringBootConfiguration
 6 @EnableAutoConfiguration
 7 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
 8         @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
 9 public @interface SpringBootApplication {
10 
11     @AliasFor(annotation = EnableAutoConfiguration.class)
12     Class<?>[] exclude() default {};
13 
14     @AliasFor(annotation = EnableAutoConfiguration.class)
15     String[] excludeName() default {};
16 
17     @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
18     String[] scanBasePackages() default {};
19     
20     @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
21     Class<?>[] scanBasePackageClasses() default {};
22 
23     @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
24     Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
25 
26     
27     @AliasFor(annotation = Configuration.class)
28     boolean proxyBeanMethods() default true;
29 }
  • @SpringBootConfiguration 配置类SpringBoot社区推荐基于JavaConfig配置方式定义Bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
  • @EnableAutoConfigurationSpringBoot实现自动配置的关键

    @Enable开头的注解,替代XML配置文件, @EnableWebMvc、@EnableScheduling // 注解之所以自动根据条件注册需要的Bean实例,主要是@Import注解导入此处@Import导入AutoConfigurationImportSelector的实现。

 1 @Target(ElementType.TYPE)
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 @Inherited
 5 @AutoConfigurationPackage
 6 @Import(AutoConfigurationImportSelector.class)
 7 public @interface EnableAutoConfiguration {
 8 
 9     String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
10 
11     Class<?>[] exclude() default {};
12 
13     String[] excludeName() default {};
14 }

    AutoConfigurationImportSelector的selectImports -> getCandidateConfigurations -> SpringFactoriesLoader.loadFactoryNames

List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

    类SpringFactoriesLoader定义常量 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    而spring-boot-autoconfigure*.jar/META-INF/spring.factories部分配置

    

     spring-boot*jar\META-INF\spring.factories 部分

    

2、SpringApplication.run

内部实现流程

1、如果使用run静态方法,那么该方法实例化一个SpringApplication对象,调用如下方法

  public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
  }

      初始化时,提前做几个事情(准备动作)

  • 根据classpath是否存在某特征类,决定是否创建供web应用使用的ApplicationContext类型
  • 使用SpringFactoriesLoader在应用classpath查找并加载所有可用的ApplicationContextInitializer
  • 使用SpringFactoriesLoader在应用classpatch查找并加载所有可用ApplicationListener

2、SpingApplication实例初始化完成并完成设置后,开始执行run方法,首先遍历执行所有通过SpringFactoriesLoader查找到并加载的SpringApplicationRunListener,调用他们的Starting方法

3、准备并配置当前spring boot应用要使用的Enviroment(含PropertySource和Profiles)

     protected void configureEnviroment(ConfirugurableEnviroment enviroment,String[] args){
          configurePropertySources(enviroment, args);

   configureProfiles(enviroment, args);

    }

4、遍历执行所有SpringApplicationRunListener的enviromentPrepared() 方法,比如创建ApplicationContext

5、判断SpringApplication的bannerMode,是CONSOLE则输出banner的System.out,是OFF则不打印,是LOG则打印到日志文件

6、判断是否设置ApplicationContextClass属性,如果有,则实例化该class;如果没有则判断是否是web环境,如果是DEFAULT_WEB_CONTEXT_CLASS,则实例化该常量对应的AnnotationConfigEmbeddedWebApplicationContext类,否则实例化DEFAULT_CONTEXT_CLASS所对应的AnnotationConfigApplicationContext类,具体如下

  public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context.annotation.AnnotationConfigApplicationContext";

  public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";

7、将之前准备好的enviroment配置给当前的ApplicationContext

8、将beanNameGenerator、resourceLoader配置给当前的ApplicationContext

9、SpringApplication通过SpringFactoriesLoader查找classpath中所有可用的AppliContextInitializer,遍历并加载ApplicationContextInitializer的initialize(context) 方法

10、遍历执行所有SpringApplicationRunListener的contextPrepared() 方法

11、为BeanDefinitionLoader配置beanNameGenerator、‘resourceLoader、enviroment,并加载之前通过@EnableAutoConfiguration获取的所有配置,及其余IOC容器配置到当前已准备完毕的ApplicationContext

12、遍历执行所有SpringApplicationRunListener的contextLoader()方法

13、调用ApplicationContext的refresh方法,完成IOC容器可用的最后工序,并为Runtime.getRuntime()添加ShutdownHook以遍JVM停止时优雅退出

14、查找ApplicationContext是否注册ApplicationRunner或CommandLineRunner,并遍历执行

15、遍历执行SpringApplicationRunListener的finished() 方法。

-- 启动完成

 

posted @ 2022-06-05 16:54  飞翔在天  阅读(182)  评论(0编辑  收藏  举报