SpringBoot系统初始化器作用
- 上下文刷新即refresh方法前调用
- 通常用在web环境中设置一些属性变量
- 可以通过order接口进行排序
1. 实现方式
- 实现ApplicationContextInitializer类
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.setRequiredProperties("mooc");
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");
}
}
- 在/resources/META-INF新建spring.factories配置文件
key值为:org.springframework.context.ApplicationContextInitializer
value值为具体的实现类:com.mooc.sb2.initializer.FirstInitializer
org.springframework.context.ApplicationContextInitializer=com.mooc.sb2.initializer.FirstInitializer
2. 源码分析
注册系统初始化器
在创建SpringApplication的时候,会注册系统初始化器
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//注册系统初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
在注册系统初始化器时,通过SpringFactoriesLoader来加载配置在spring.factories配置文件中的系统初始化器。
SpringFactoriesLoader是spring内部使用的通用工厂加载机器,从classpath下的多个jar包读取/resources/META-INF/spring.factories内容。文件内容必须是kv形式,key为全限定名,value为实现,多个实现用逗号进行分割。
调用系统初始化器
在refresh方法之前,prepareContext方法中会调用系统初始化器,源码如下:
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
//调用系统初始化器
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
网友评论