跳至主要內容

Spring Boot系统初始化器

向往大约 2 分钟Spring BootApplicationContextInitializerSpring Boot

概述

系统初始化器类名为ApplicationContextInitializer,是ApplicationContextInitializerSpring.initialize容器刷新之前执行的一个回调函数,作用是向SpringBoot容器中注册属性。

使用

声明自定义初始化器注入属性到容器中

package tech.xiangwang.sbdemo.initializer;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @author: blog.xiangwang.tech
 * @create: 2022-12-03 16:57
 **/
public class TestInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {


    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String, Object > map = new HashMap<>();
        map.put("key1", "value1");
        MapPropertySource mapPropertySource = new MapPropertySource("first",map);
        environment.getPropertySources().addLast(mapPropertySource);
        System.out.println("run TestInitializer");
    }
}

有三种方式将初始化器进行注册:

  • 定义在src/main/resources/META-INF/spring.factories文件中被SpringFactoriesLoader注册发现。

    org.springframework.context.ApplicationContextInitializer =tech.xiangwang.sbdemo.initializer.TestInitializer
    
  • SpringApplication初始化完毕后手动添加

    @SpringBootApplication
    public class  SbDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(SbDemoApplication.class);
            springApplication.addInitializers(new TestInitializer());
            springApplication.run(args);
        }
    
    }
    
  • src/main/resources/application.properties定义成环境变量被DelegatingApplicationContextInitializer发现注册。

    context.initializer.classes=tech.xiangwang.sbdemo.initializer.TestInitializer
    

流程

SpringFactoriesLoader 读取初始化器代码如下

image-20221203211710185

进一步查看org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames方法,

流程:从classpath下多个jar包读取META-INF/spring.factories读取文件并初始化类,文件内容必须是kv形式,即properties类型,key是全限定名(接口、抽象类)、value是实现,多个实现用,分隔

image-20221203212255476

初始化器执行时机在准备上下文阶段,org.springframework.boot.SpringApplication#applyInitializers 方法会将上方法返回的初始化器进行初始化操作,debug视图如下,

image-20221203213354862

排序根据Order从小到大的顺序进行依次执行

总结

  • 初始化器用于向容器中注册属性和环境配置
  • SpringFactoriesLoader这个类实现了检索META-INF/spring.factories文件,并获取指定接口的配置的功能。在很多内置的start模块有使用到了该配置,可以做到自动配置,达到开箱即用的效果。