系统初始化器介绍
原理
- 类名ApplicationContextInitializer
- 介绍Spring容器刷新之前执行的回调函数
- 向SpringBoot容器中注册属性
- 继承接口自定义实现
实现方式
方法一
1.创建FirstInitializer类实现ApplicationContextInitializer接口
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run firstInitializer");
}
}
2.resource下创建META-INF/spring.factories文件,配置属性
org.springframework.context.ApplicationContextInitializer=com.example.demo.initializer.FirstInitializer
方法二
- 创建SecondInitializer类实现ApplicationContextInitializer接口
@Order(2)
public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key2", "value2");
MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run secondInitializer");
}
}
- 启动类里,手动添加初始化示例
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addInitializers(new SecondInitializer());
application.run(args);
}
}
方法三
- 创建ThirdInitializer类实现ApplicationContextInitializer接口
@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key3", "value3");
MapPropertySource mapPropertySource = new MapPropertySource("thirdInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run thirdInitializer");
}
}
- 在resource下的application.properties里添加配置
context.initializer.classes=com.example.demo.initializer.ThirdInitializer
tips:application.properties里配置,是DelegatingApplicationContextInitializer实现读取初始化配置的方法,该方法order=0,所以第一个执行该初始化
注意
- 都要是实现ApplicationContextInitializer接口
- Order值越小越先执行
- application.properties中定义的优先于其他方式
SpringFactoriesLoader介绍
原理
- 框架内部使用的通用工厂加载机制
- 从classpath下多个jar包特定的位置读取文件并初始化类
- 文件内容必须是kv形式,即properties类型
- key是全限定名(抽象类|接口)、value是实现,多个实现用,分割
框架初始化步骤
SpringFactoriesLoader作用
SpringBoot框架中从类路径jar包中读取特定文件实现扩展类的载入
loadFactoies流程
系统初始化器原理解析
作用
- 上下文刷新即refresh方法前调用
- 用来编码设置一些属性变量通常用在web环境中
- 可以通过order接口进行排序
调用点
调用流程
实现原理
- 定义在spring.factories文件中被SpringFactoriesLoader发现注册
- SpringApplication初始化完毕后手动添加
- 定义成环境变量被DelegatingApplicationContextInitializer发现注册
面试题
介绍下SpringFactoriesLoader?
SpringBoot工厂的加载类, SpringBoot用它完成扩展点的载入
SpringFactoriesLoader如何加载工厂类?
读取指定路径下的指定文件,把他们读取成property对象,依次遍历文件内容,组装成类名和对应的实现,通过order进行排序。
系统初始化器的作用?
他其实是SpringBoot容器的一个回调接口,我们可以向SpringBoot容器定义我们的属性。
系统初始化器调用时机?
在springboot启动过程中的prepareContext过程中调用