Springboot启动过程中在刷新IOC容器之前主要包括三大部分功能完善:ApplicationContextInitializer
、ApplicationListener
、EnvironmentPostProcessor
。
ApplicationContextInitializer 主要用在容器刷新之前调用改接口实现类的 initialize 方法,并将 ConfigurableApplicationContext 类的实例作为参数传入。通常用于根据应用上下文进行处理的编程中。且实现类可以通过 Ordered 接口或 @Order 注解 进行多个 Initializer 的排序。
public class SpringApplication {
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationListener<?>> listeners;
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
...
//初始化ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//初始化应用监听器AnnotationConfigServletWebServerApplicationContext
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
}
public ConfigurableApplicationContext run(String... args) {
...
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 实例化StandardServletEnvironment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//实例化应用上下文
ConfigurableApplicationContext context = createApplicationContext();
//应用上下文与StandardServletEnvironment的绑定操作
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.started(context);
callRunners(context, applicationArguments);
listeners.running(context);
return context;
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
//执行ApplicationListener类型的监听器
listeners.environmentPrepared(environment);
// 利用上述得到的配置value动态控制SpringApplication实例中属性值
bindToSpringApplication(environment);
....
ConfigurationPropertySources.attach(environment);
return environment;
}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 执行各种类型的ApplicationContextInitializer
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
...
Set<Object> sources = getAllSources();
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
}
在SpringApplication的构造器中通过Spi机制获取到类名之后,通过反射完成实例化。对参数initializers
、listeners
进行复制。具体取值如spring.factories文件:
核心spring-boot.jar、spring-beans.jar包下的spring.factories文件。
1、自定义ApplicationContextInitializer
spring-boot.jar#spring.factories部分内容如下:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer,
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
@Slf4j
public class CustomApplicationContextInitializer implements ApplicationContextInitializer {
@Override//AnnotationConfigServletWebServerApplicationContext
public void initialize(ConfigurableApplicationContext applicationContext) {
log.error("========== this is custom applicationContextInitializer ===============");
}
}
Apollo之
ApolloApplicationContextInitializer
。
1.1、方式一
SpringApplication springApplication = new SpringApplication(BootApp.class);
springApplication.addInitializers(new CustomApplicationContextInitializer());
ConfigurableApplicationContext run = springApplication.run(args);
1.2、方式二
SPI 扩展 META-INF/spring.factories:
org.springframework.context.ApplicationContextInitializer=\
boot.initializer.Custom3ApplicationContextInitializer
1.3、方式三
在配置文件 application.properties 中添加如下配置:
context.initializer.classes = boot.initializer.Custom2ApplicationContextInitializer
2.ApplicationListener
spring-boot.jar#spring.factories部分内容如下:
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
比较常见的内置监听器包括ConfigFileApplicationListener
、BootstrapApplicationListener
等。
3.EnvironmentPostProcessor
spring-boot.jar#spring.factories部分内容如下:
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor,\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
目前只发现在执行ConfigFileApplicationListener
监听器时涉及该类型的后置处理器。示例参考Apollo之ApolloApplicationContextInitializer。