系统初始化器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
/**
* @author itning
* @date 2020/4/28 20:43
*/
@Order(1)
public class FirstApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(@NonNull ConfigurableApplicationContext applicationContext) {
System.out.println("FirstApplicationContextInitializer");
}
}
|
实现ApplicationContextInitializer
接口即可,并且必须是ConfigurableApplicationContext
子类
如何使其生效?三种方式:
关键代码:springApplication.addInitializers(new FirstApplicationContextInitializer());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import top.itning.springboottest.config.FirstApplicationContextInitializer;
/**
* @author itning
*/
@SpringBootApplication
public class SpringbootTestApplication {
public static void main(String[] args) {
//SpringApplication.run(SpringbootTestApplication.class, args);
SpringApplication springApplication = new SpringApplication(SpringbootTestApplication.class);
springApplication.addInitializers(new FirstApplicationContextInitializer());
springApplication.run(args);
}
}
|
只需要在应用配置文件中application.yml
配置:context.initializer.classes=xxx.xxx.xxx.XX
1
2
3
| context:
initializer:
classes: xxx.xxx.xxx.XX
|
resources
目录新建META-INF
文件夹并且新建文件:spring.factories
1
| org.springframeword.context.ApplicationContextInitializer=xxx.xxx.xxx.XX
|
源码解析;
1
2
3
| public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
|
实例化SpringApplication
的代码:
1
2
3
4
5
6
7
8
9
| 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();
}
|
关键代码:setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
1
2
3
| private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
|
泛型T
即为ApplicationContextInitializer
1
2
3
4
5
6
7
8
| private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
|
首先,获得类加载器:ClassLoader classLoader = getClassLoader();
然后,Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
通过调用静态方法SpringFactoriesLoader.loadFactoryNames(type, classLoader)
来获得所有定义org.springframeword.context.ApplicationContextInitializer
的值
最后进行排序。
当调用run()
方法时:
1
| prepareContext(context, environment, listeners, applicationArguments, printedBanner);
|
会调用
1
| applyInitializers(context);
|
同过for
循环来调用initialize
方法:
1
2
3
4
5
6
7
8
| 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);
}
}
|
其中第一个被调用initialize
的类是org.springframework.boot.context.config.DelegatingApplicationContextInitializer
,该类会加载在application.yml
中属性为private static final String PROPERTY_NAME = "context.initializer.classes";
的类并进行调用initialize
方法
而springApplication.addInitializers(new FirstApplicationContextInitializer());
直接将参数加入到List
集合中。
1
2
3
4
5
| private List<ApplicationContextInitializer<?>> initializers;
public void addInitializers(ApplicationContextInitializer<?>... initializers) {
this.initializers.addAll(Arrays.asList(initializers));
}
|
文章作者
itning
上次更新
2020年04月28日 21:05:39
许可协议
CC BY-NC-ND 4.0