Spring Boot中可以使用三种方式生成自定义初始化器
自定义初始化器有什么用?
- SpringBoot 初始化器 ApplicationInitializer
- 初始化器是Spring容器刷新之前执行的一个回调函数
- 主要作用是向SpringBoot容器中注册属性
- 使用方式实现ApplicationContextInitializer接口
调用流程
![v2-4a0bcf7d64bcf0df662f329175ff2478_b.jpg](https://img-blog.csdnimg.cn/img_convert/96fc6ff62f184c966b66d9d93872bbfc.png)
实现原理
- 定义在META-INF的文件spring.factories会被SpringFactoriesLoader发现注册
- SpringApplication初始化完毕后手动添加
- 定义成环境变量被DelegatingApplicationContextinitializer发现注册。(DelegatingApplicationContextInitializer会被SpringFactories发现并注册。DelegatingApplicationContextInitializer存在属性context.initializer.classes的配置,且order默认为0,所以通过该属性配置的自定义初始化器优先级最高)
三种实现方式
三种方式的共同特点都需实现applicationContextInitializer<ConfigurableApplicationContext>接口。
设置@Order
- 第一种方式通过META-INF去配置自定义系统初始化器
@Order(1)
public class FirstInitializer implements ApplicationInitializer<ConfigurableApplicationContext>{
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key1","value1");
MapPropertySource firstInitializer = new MapPropertySource("firstInitializer", map);
environment.getPropertySources().addLast(firstInitializer);
System.out.println("run firstInitializer");
}
}
//1. 在resources下创建文件夹META-INF
//2. 新建文件spring-factories
//3. 使用key-value的方式指定自定义初始化器
org.springframework.context.ApplicationContextInitializer=me.zhyx.spring.demo.demo.init.FirstInitializer
- 第二种方式重写启动类main方法
//第一步都一样
@Order(2)
public class SecondInitializer implements ApplicationInitializer<ConfigurableApplicationContext>{
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key2","value2");
MapPropertySource firstInitializer = new MapPropertySource("SecondInitializer", map);
environment.getPropertySources().addLast(firstInitializer);
System.out.println("run SecondInitializer");
}
}
//1. 在启动类中修改启动流程
//2. 往初始化方法中添加一个自定义系统初始化器。
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
- 第三种通过application.properties去配置自定义系统初始化器。这种方式优先级最高
//第一步都一样
@Order(3)
public class SecondInitializer implements ApplicationInitializer<ConfigurableApplicationContext>{
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key2","value2");
MapPropertySource firstInitializer = new MapPropertySource("SecondInitializer", map);
environment.getPropertySources().addLast(firstInitializer);
System.out.println("run SecondInitializer");
}
}
//1. 修改application.properties
//2. context.initializer.classes=xxx
context.initializer.classes=me.zhyx.spring.demo.demo.init.ThirdInitializer
配置完之后,可以通过实现ApplicationContextAware接口去拿到对应的值
@Component
public class TestService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public String test(){
return applicationContext.getEnvironment().getProperty("key3");
}
}
如何往应用程序中添加必备的属性?
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//将Test作为必备的属性添加到环境变量当中
environment.setRequiredProperties("Test");
}
}
//需要在配置文件中指定该值
Test=xxxx
否则在
refresh
>prepareRefresh
>getEnvironment().validateRequiredProperties()
进行校验的时候就会抛出异常直接启动失败。