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方法中使用

@SpringBootApplication

public 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

启动类:

@SpringBootApplication

public 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

回到顶部