ApplicationContextInitializer的使用
1.介绍
ApplicationContextInitializer主要用在容器刷新之前调用改接口实现类的initialize方法,并将ConfigurableApplicationContext类的实例作为参数传入。通常用于根据应用上下文进行处理的编程中。且实现类可以通过Ordered接口或 @Order注解 进行多个Initializer的排序。
2.有三种使用方式
首先定义一个测试initializer
public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("Initializer调用:" + applicationContext.getApplicationName());
}
@Override
public int getOrder() {
return 0;
}
}
第一种:在启动类的main方法中使用
@SpringBootApplicationpublic class DemoApplication {
public static void main(String[] args) {
// SpringApplication.run(DemoApplication.class, args);
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addInitializers(new TestApplicationContextInitializer()); // 直接在SpringApplication中添加
application.run(args);
System.out.println("启动完成");
}
}
输出结果:
. ____ _ __ _ _
/\ / ___"_ __ _ _(_)_ __ __ _
( ( )\___ | "_ | "_| | "_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
" |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
Initializer调用:
2020-03-18 19:15:09.448 INFO 87824 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on ZZ-WZ112019 with PID 87824 (E:java_workdemo argetclasses started by jiafeng in E:java_workdemo)
2020-03-18 19:15:09.454 INFO 87824 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2020-03-18 19:15:09.950 INFO 87824 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 116.167 seconds (JVM running for 116.788)
启动完成
第二种:通过SPI扩展META-INF/spring.factories使用
spring.factories文件
org.springframework.context.ApplicationContextInitializer=com.example.demo.initializer.TestApplicationContextInitializer
启动类:
@SpringBootApplicationpublic class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
// SpringApplication application = new SpringApplication(DemoApplication.class);
// application.addInitializers(new TestApplicationContextInitializer()); // 直接在SpringApplication中添加
// application.run(args);
System.out.println("启动完成");
}
}
输出结果:同上产生效果
. ____ _ __ _ _ /\ / ___"_ __ _ _(_)_ __ __ _
( ( )\___ | "_ | "_| | "_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
" |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
Initializer调用:
2020-03-18 19:20:23.812 INFO 87920 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on ZZ-WZ112019 with PID 87920 (E:java_workdemo argetclasses started by jiafeng in E:java_workdemo)
2020-03-18 19:20:23.814 INFO 87920 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2020-03-18 19:20:24.057 INFO 87920 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.443 seconds (JVM running for 0.932)
启动完成
第三种:通过配置文件使用
在配置文件application.properties中添加如下配置:
context.initializer.classes=com.example.demo.initializer.TestApplicationContextInitializer
运行启动类,依然被调用。
3. Ordered排序
通过继承Ordered接口实现int getOrder()方法进行排序,设置高优先级排序则在众多initializer中会被优先调用。
@Override public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
4. 源码分析initializer运行时机
SpringApplication实例化对象时会对所有initializer进行加载。
SpringApplication的run( )方法:
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//刷新之前准备工作,在该方法进行initialize调用
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//进行刷新
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
prepareContext( )方法中
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
//执行initialize调用
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);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 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);
}
在applyInitializers( )方法中对前面加载的initializer进行循环遍历调用initialize方法
@SuppressWarnings({ "rawtypes", "unchecked" }) protected void applyInitializers(ConfigurableApplicationContext context) {
//遍历SpringApplication实例化时加载的所有initializer
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);//调用initialize实现方法
}
}
以上是 ApplicationContextInitializer的使用 的全部内容, 来源链接: utcz.com/z/514510.html