1、Spring Boot 系统初始化器
系统初始化器介绍
SpringFactoriesLoader介绍
系统初始化器原理
2、系统初始化器介绍
类名: ApplicationContextinitializer
介绍: Spring容量刷新之前执行的一个回调函数
作用: 向SpringBoot容器中注册属性
使用:继承接口自定义实现
3、系统初始化器实践
创建系统初始化器方式一(实现原理:定义在spring.factories 文件中被SpringFactoriesLoader发现注册)
1)创建初始化器
在包initializer下创建FirstInitializer
/**
*
* 第一个系统初始化器
*/
@Order(1)
public class FirstInitializer 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("firstInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run FirstInitializer");
}
}
2) 创建spring.factories

内容为:
org.springframework.context.ApplicationContextInitializer=com.example.demo.initialize.FirstInitializer
3) 创建服务类 TestService
@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("key1");
}
}
4) 在Controller层增加方法
@RequestMapping("/test")
@ResponseBody
public String test(){
return testService.test();
}
5) 启动工程查看效果
可以发现打印了run FirstInitializer

然后调用接口。返回值为之前设置的value1

创建系统初始化器方式二(实现原理:初始化完毕手动添加)
1)订单创建初始化器
@Order(2)
public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.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");
}
}
2) SB2Application改成如下
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class Sb2Application {
public static void main(String[] args) {
//SpringApplication.run(Sb2Application.class, args);
SpringApplication springApplication = new SpringApplication(Sb2Application.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
}
}
3) 修改Service的test方法
public String test(){
return applicationContext.getEnvironment().getProperty("key2");
}
4)启动(说明两个初始化器都已经创建)
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _
( ( )\___ | '_ | '_| | '_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
run FirstInitializer
run SecondInitializer
5)、测试返回结果。返回value2

创建系统初始化器方式三(实现原理:定义成环境变量被DelegatingApplicationContextInitializer发现注册)
1)创建初始化器
@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.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");
}
}
2) 在application.properties 增加
context.initializer.classes=com.example.demo.initializer.ThirdInitializer

3)、修改TestServer的test方法
public String test(){
return applicationContext.getEnvironment().getProperty("key3");
}
4) 启动测试

可以发现打印的顺序和定义的不一致。第三个ThirdInitializer初始化器优先于第一个和第二个打印出来。
使用接口测试,返回value2

那springboot初始化器是如何被识别呢,靠的就是SpringFactoriesLoader
springboot初始化器原理:
初始化SpringApplication 工厂加载机制 SpringFactoriesLoader
调用run方法: Spring Boot 系统初始化器是如何被调用的,以及实现原理