ApplicationContextInitializer
目录
- 在何处执行?
- 何时初始化?
- 那这个类的设计具体有什么作用呢??
- 1. DelegatingApplicationContextInitializer
- 2. SharedMetadataReaderFactoryContextInitializer
- 3. ContextIdApplicationContextInitializer
- 4. ConfigurationWarningsApplicationContextInitializer
- 5. RSocketPortInfoApplicationContextInitializer
- 6. ServerPoerInfoApplicationContextInitializer
- 7. ConditionEvaluationReportLoggingListener
- 总结
在何处执行?
执行时机在SpringApplication类的prepareContenxt中,在run
方法中可以找到prepareContext方法。
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
...
// 执行applyInitializers
applyInitializers(context);
...
}
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
何时初始化?
在SpringApplication构造函数中会初始化initializers。
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
...
// 初始化initializers
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
...
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 在META-INF/spring.factories中寻找实现类。
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
自己写一个ApplicationContextInitializer
public class OrangeInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("my initializer");
}
}
在resources的META-INF中创建一个spring.factories文件,下面是我的例子,具体的路径还是看自己的。
org.springframework.context.ApplicationContextInitializer=\
com.example.spring.spring.listener.OrangeInitializer
可以看到启动SpringBoot之后,my initializer
打印出来了。
那这个类的设计具体有什么作用呢??
想要知道这里类的作用,切入点就是看看它的实现类都干了什么事情,下面八个类,有一个OrangeInitializer是自定义的,其他七个是SpringBoot启动就有的。当然也可以从名称上去猜测,他就是用来初始化ApplicationContext的。看一下它的默认实现都干了什么事情!
1. DelegatingApplicationContextInitializer
private static final String PROPERTY_NAME = "context.initializer.classes";
@Override
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
// 获取对象
List<Class<?>> initializerClasses = getInitializerClasses(environment);
// 执行具体的ApplicationContextInitializer
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
// 从Environment中拿context.initializer.classes。
String classNames = env.getProperty(PROPERTY_NAME);
List<Class<?>> classes = new ArrayList<>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
classes.add(getInitializerClass(className));
}
}
return classes;
}
通过配置文件去注入ApplicationContextInitializer。
public class EnvironmentInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("my environmentInitializer");
}
}
application.yml
如果自己有多个类,可以用英文逗号隔开
context:
initializer:
classes: com.example.spring.spring.initializer.EnvironmentInitializer
2. SharedMetadataReaderFactoryContextInitializer
这个就简单多了,就把一个BeanFactoryPostProcessor放入到ConfigurableApplicationContext中,会在AbstractApplicationContext的refresh的invokeBeanFactoryPostProcessors去执行。
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
BeanFactoryPostProcessor postProcessor = new CachingMetadataReaderFactoryPostProcessor(applicationContext);
applicationContext.addBeanFactoryPostProcessor(postProcessor);
}
3. ContextIdApplicationContextInitializer
也不知道作用是啥。
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ContextId contextId = getContextId(applicationContext);
applicationContext.setId(contextId.getId());
applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(), contextId);
}
4. ConfigurationWarningsApplicationContextInitializer
也是添加一个BeanFactoryPostProcessor处理器。
@Override
public void initialize(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}
5. RSocketPortInfoApplicationContextInitializer
不知道是干什么的
6. ServerPoerInfoApplicationContextInitializer
7. ConditionEvaluationReportLoggingListener
不知道
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
applicationContext.addApplicationListener(new ConditionEvaluationReportListener());
if (applicationContext instanceof GenericApplicationContext) {
// Get the report early in case the context fails to load
this.report = ConditionEvaluationReport.get(this.applicationContext.getBeanFactory());
}
}
总结
- ApplicationContextInitializer是用来填充ApplicationContext各种属性的
- 在refresh之前执行
- 有spring.factories / application.yml两种方法进行自定义扩展