Application context生命周期事件
public class SpringEventListenerBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(Object.class)
.listeners(
event -> System.out.println(
event.getClass().getSimpleName()+
",事件源:" + event.getSource().getClass().getName()
)).web(WebApplicationType.NONE).run().close();
}
}
![]()
输出:
ApplicationStartingEvent,事件源:org.springframework.boot.SpringApplication
ApplicationEnvironmentPreparedEvent,事件源:org.springframework.boot.SpringApplication
ApplicationContextInitializedEvent,事件源:org.springframework.boot.SpringApplication
ApplicationPreparedEvent,事件源:org.springframework.boot.SpringApplication
ContextRefreshedEvent,事件源:org.springframework.context.annotation.AnnotationConfig
ApplicationContextApplicationStartedEvent,事件源:org.springframework.boot.SpringApplication
ApplicationReadyEvent,事件源:org.springframework.boot.SpringApplication
ContextClosedEvent,事件源:org.springframework.context.annotation.AnnotationConfigApplicationContext
ApplicationListener
-
org.springframework.boot.ClearCachesApplicationListener
监听ContextRefreshedEvent事件,根据classLoader向上级递归查找clearCache方法,主要作用是清除ReflectionUtils和ClassLoader缓存
@Override public void onApplicationEvent(ContextRefreshedEvent event) { ReflectionUtils.clearCache(); clearClassLoaderCaches(Thread.currentThread().getContextClassLoader()); } private void clearClassLoaderCaches(ClassLoader classLoader) { if (classLoader == null) { return; } try { Method clearCacheMethod = classLoader.getClass().getDeclaredMethod("clearCache"); clearCacheMethod.invoke(classLoader); } catch (Exception ex) { // Ignore } clearClassLoaderCaches(classLoader.getParent()); } -
org.springframework.boot.builder.ParentContextCloserApplicationListener
监听ParentContextAvailableEvent事件,当前的应用上线文有parent context时,向parent context中注册ContextCloserListener,当parent context关闭时通知子容器
@Override public void onApplicationEvent(ParentContextAvailableEvent event) { maybeInstallListenerInParent(event.getApplicationContext()); } private void maybeInstallListenerInParent(ConfigurableApplicationContext child) { if (child == this.context && child.getParent() instanceof ConfigurableApplicationContext) { ConfigurableApplicationContext parent = (ConfigurableApplicationContext) child .getParent(); parent.addApplicationListener(createContextCloserListener(child)); } } -
FileEncodingApplicationListener
检测当前系统环境的file.encoding和spring.mandatory-file-encoding设置的值是否一样 ,不一样则抛出IllegalStateException异常
@Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { ConfigurableEnvironment environment = event.getEnvironment(); if (!environment.containsProperty("spring.mandatory-file-encoding")) { return; } String encoding = System.getProperty("file.encoding"); String desired = environment.getProperty("spring.mandatory-file-encoding"); if (encoding != null && !desired.equalsIgnoreCase(encoding)) { logger.error("System property 'file.encoding' is currently '" + encoding + "'. It should be '" + desired + "' (as defined in 'spring.mandatoryFileEncoding')."); logger.error("Environment variable LANG is '" + System.getenv("LANG") + "'. You could use a locale setting that matches encoding='" + desired + "'."); logger.error("Environment variable LC_ALL is '" + System.getenv("LC_ALL") + "'. You could use a locale setting that matches encoding='" + desired + "'."); throw new IllegalStateException( "The Java Virtual Machine has not been configured to use the " + "desired default character encoding (" + desired + ")."); } } -
org.springframework.boot.context.config.AnsiOutputApplicationListener
监听ApplicationEnvironmentPreparedEvent事件,获取Environment的spring.output.ansi.enabled, 设置彩色输出会让日志更具可读性
-
org.springframework.boot.context.config.ConfigFileApplicationListener
监听ApplicationEnvironmentPreparedEvent和ApplicationPreparedEvent事件,且ConfigFileApplicationListener也实现了EnvironmentPostProcessor接口,ApplicationEnvironmentPreparedEvent事件会加载外部化配置文件,如 application.yaml和application.perprotiess
@Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationEnvironmentPreparedEvent) { onApplicationEnvironmentPreparedEvent( (ApplicationEnvironmentPreparedEvent) event); } if (event instanceof ApplicationPreparedEvent) { onApplicationPreparedEvent(event); } } @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { addPropertySources(environment, application.getResourceLoader()); } ......... /** * Add config file property sources to the specified environment. * @param environment the environment to add source to * @param resourceLoader the resource loader * @see #addPostProcessors(ConfigurableApplicationContext) */ protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) { RandomValuePropertySource.addToEnvironment(environment); new Loader(environment, resourceLoader).load(); }ApplicationEnvironmentPreparedEvent
通过SpringFactoriesLoader.loadFactories加载EnvironmentPostProcessor,EnvironmentPostProcessor实现有以下4个:
SystemEnvironmentPropertySourceEnvironmentPostProcessor
增加
SystemEnvironmentPropertySource到PropertySources中SpringApplicationJsonEnvironmentPostProcessor
解析PropertySources中的JsonPropertyValue
CloudFoundryVcapEnvironmentPostProcessor
解析vcap的环境信息
ConfigFileApplicationListener
通过一个内部类
Loader加载和解析application.properteis和application.yamlApplicationPreparedEvent
注册一个实现了实现了BeanFactoryPostProcessor接口的PropertySourceOrderingPostProcessor,主要作用是对 property sources进行重排序
-
org.springframework.boot.context.config.DelegatingApplicationListener
注册在environment中的配置的context.listener.classes监听器
-
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener
日志级别为debug级别时,在环境准备完成事件ApplicationEnvironmentPreparedEvent或者应用失败事件ApplicationFailedEvent 发生时,输出线程上下文类加载器的classpath
-
org.springframework.boot.context.logging.LoggingApplicationListener
识别日志框架,并加载日志配置文件
-
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
监听ApplicationStartingEvent事件,取代liquibase ServiceLocator
-
org.springframework.boot.autoconfigure.BackgroundPreinitializer
监听ApplicationReadyEvent和ApplicationFailedEvent事件,异步线程触发早期的初始化操作
在spring容器初始化前,会通过SpringApplicationRunListener触发ApplicationStartedEvent事件,在容器实例化完成后触发ApplicationReadyEvent事件
SpringApplicationRunListener
SpringApplication 通过SpringFactoriesLoader从META-INF/spring.factories资源中加载其实现类EventPublishingRunListener,EventPublishingRunListener与spring boot事件的关系,以及AbstractApplication调用前后关系:
| 监听方法 | refresh()方法执行顺序 | springboot事件 |
|---|---|---|
| started() | 调用前 | ApplicationStartedEvent |
| environmentPrepared() | 调用前 | ApplicationEnvironmentPreparedEvent |
| contextLoad() | 调用前 | ApplicationPreparedEvent |
| running() | 调用后 | ApplicationReadyEvent |
| failed() | 调用后 | ApplicationFailedEvent |
org.springframework.boot.context.event.EventPublishingRunListener
在实例化
EventPublishingRunListener的过程中,会给它最重要的属性initialMulticaster赋值,其类型是SimpleApplicationEventMulticaster。接着遍历 SpringApplication 初始化阶段的listeners监听器集合,将监听器存入其关联的ListenerRetriever#applicationListeners属性中
本文详细介绍了Spring Boot中Application Context的生命周期事件,包括ApplicationListener、SpringApplicationRunListener。重点讲解了ContextRefreshedEvent事件的处理,如何清除缓存,以及ParentContextAvailableEvent事件的处理,如何在父上下文中注册监听器。同时,提到了FileEncodingApplicationListener用于检查文件编码,AnsiOutputApplicationListener用于设置彩色输出,ConfigFileApplicationListener用于加载外部配置文件,以及各种EnvironmentPostProcessor的实现。

2340

被折叠的 条评论
为什么被折叠?



