spring springBoot事件

本文详细介绍了Spring Boot中Application Context的生命周期事件,包括ApplicationListener、SpringApplicationRunListener。重点讲解了ContextRefreshedEvent事件的处理,如何清除缓存,以及ParentContextAvailableEvent事件的处理,如何在父上下文中注册监听器。同时,提到了FileEncodingApplicationListener用于检查文件编码,AnsiOutputApplicationListener用于设置彩色输出,ConfigFileApplicationListener用于加载外部配置文件,以及各种EnvironmentPostProcessor的实现。

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

  1. 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());
       }
  2. 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));
         }
     }
  3. 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 + ").");
         }
     }
  4. org.springframework.boot.context.config.AnsiOutputApplicationListener

    监听ApplicationEnvironmentPreparedEvent事件,获取Environment的spring.output.ansi.enabled, 设置彩色输出会让日志更具可读性

  5. 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

    增加SystemEnvironmentPropertySourcePropertySources

    SpringApplicationJsonEnvironmentPostProcessor

    解析PropertySources中的JsonPropertyValue

    CloudFoundryVcapEnvironmentPostProcessor

    解析vcap的环境信息

    ConfigFileApplicationListener

    通过一个内部类Loader加载和解析application.properteis和application.yaml

    ApplicationPreparedEvent

    注册一个实现了实现了BeanFactoryPostProcessor接口的PropertySourceOrderingPostProcessor,主要作用是对 property sources进行重排序

  6. org.springframework.boot.context.config.DelegatingApplicationListener

    注册在environment中的配置的context.listener.classes监听器

  7. org.springframework.boot.context.logging.ClasspathLoggingApplicationListener

    日志级别为debug级别时,在环境准备完成事件ApplicationEnvironmentPreparedEvent或者应用失败事件ApplicationFailedEvent 发生时,输出线程上下文类加载器的classpath

  8. org.springframework.boot.context.logging.LoggingApplicationListener

    识别日志框架,并加载日志配置文件

  9. org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

    监听ApplicationStartingEvent事件,取代liquibase ServiceLocator

  10. 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属性中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值