文章目录
- 一、认识ApplicationContextInitializer
- 1、ApplicationContextInitializer的作用
- 2、认识ApplicationContextInitializer接口
- 3、ApplicationContextInitializer的常用用法
- (1)注册BeanFactoryPostProcessor
- (2)注册ApplicationListener监听器
- (3)处理Environment运行环境(获取、修改配置等)
- (4)设置ApplicationContext的parent
- (5)注册Bean
- (6)注册BeanPostProcessor
- 二、使用ApplicationContextInitializer
- 1、定义ApplicationContextInitializer实现类
- 2、注册ApplicationContextInitializer
- (1)在resources/META-INF/spring.factories配置
- (2)代码注册
- (3)配置文件注册
- 3、查看结果
- 4、设置执行顺序
- 三、源码分析
- 1、加载ApplicationContextInitializer
- 2、执行时机
- 参考资料
一、认识ApplicationContextInitializer
1、ApplicationContextInitializer的作用
ApplicationContextInitializer接口的执行时机:用于在刷新之前初始化Spring ConfigurableApplicationContext的回调接口。
通常在需要对应用程序上下文进行一些编程初始化的web应用程序
中使用。例如,根据上下文环境注册属性源或激活概要文件
。
2、认识ApplicationContextInitializer接口
ApplicationContextInitializer接口只有一个方法,实现该方法会获得一个ConfigurableApplicationContext的回调。
@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
3、ApplicationContextInitializer的常用用法
(1)注册BeanFactoryPostProcessor
(2)注册ApplicationListener监听器
(3)处理Environment运行环境(获取、修改配置等)
(4)设置ApplicationContext的parent
(5)注册Bean
(6)注册BeanPostProcessor
二、使用ApplicationContextInitializer
1、定义ApplicationContextInitializer实现类
public class FirstInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key1", "First");
MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run firstInitializer");
}
}
public class SecondInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key1", "Second");
MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run secondInitializer");
}
}
public class ThirdInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key1", "Third");
MapPropertySource mapPropertySource = new MapPropertySource("thirdInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run thirdInitializer");
}
}
2、注册ApplicationContextInitializer
(1)在resources/META-INF/spring.factories配置
org.springframework.context.ApplicationContextInitializer=com.learn.springboot.initializer.FirstInitializer
(2)代码注册
SpringApplication springApplication = new SpringApplication(SpringbootApplication.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run();
(3)配置文件注册
context.initializer.classes=com.learn.springboot.initializer.ThirdInitializer
3、查看结果
可以看到配置生效了,并且三种配置优先级不一样,配置文件优先级最高,spring.factories 其次,代码最后。
run thirdInitializer
run firstInitializer
run secondInitializer
4、设置执行顺序
可以通过@Order
或者实现org.springframework.core.Ordered
接口并重写setOrder
方法设置顺序,@Order
值越小,执行优先级越高。
三、源码分析
springboot启动流程,手把手打断点一步步看运行步骤
1、加载ApplicationContextInitializer
在Springboot启动时,会加载所有META-INF/spring.factories
中定义的ApplicationContextInitializer
如果用SpringApplication的addInitializers
方法添加,相当于直接添加到这个List中:
2、执行时机
在springboot启动,调用prepareContext方法时:
所以说,initialize方法是在IOC容器启动之前执行的,此时的容器还未初始化,只能做一些容器启动前的准备工作。
参考资料
https://zhuanlan.zhihu.com/p/509824476
https://mp.weixin.qq.com/s/_kTPz22QY9fZXmyYtE-Ulw