如何在bean实例化之前记录spring引导应用程序的所有活动属性?

时间:2018-01-11 17:26:49

标签: java spring spring-boot logging startup

已经有question要求记录活动配置,有一个正确的answer但问题是只有在正确实例化所有bean的情况下才会记录配置。如果应用程序在启动时崩溃,我甚至(主要)记录所有属性。我的问题更具体:

如何在bean实例化之前记录Spring引导应用程序的所有活动属性?

1 个答案:

答案 0 :(得分:8)

为此,您需要注册ApplicationListener。根据文档:

,要捕获的事件是ApplicationPreparedEvent
  

当SpringApplication启动时,[ApplicationPreparedEvent发布了] []   ApplicationContext已完全准备好但未刷新。豆子   将加载定义并准备好使用环境   这个阶段。

主要方法如下:

public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(MyApplication.class);
        springApplication.addListeners(new PropertiesLogger());
        springApplication.run(args);        
}

我已经重复使用了当前问题中引用的答案代码,但我修改了它,因为您获得的上下文尚未刷新,并且环境结构与应用程序启动后的结构不完全相同。我还按属性源打印了属性:一个用于系统环境,一个用于系统属性,一个用于应用程序配置属性等...

package com.toto.myapp.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;

import java.util.LinkedList;
import java.util.List;

public class PropertiesLogger implements ApplicationListener<ApplicationPreparedEvent> {
  private static final Logger log = LoggerFactory.getLogger(PropertiesLogger.class);

  private ConfigurableEnvironment environment;

  @Override
  public void onApplicationEvent(ApplicationPreparedEvent event) {
    environment = event.getApplicationContext().getEnvironment();
    printProperties();
  }

  public void printProperties() {
    for (EnumerablePropertySource propertySource : findPropertiesPropertySources()) {
      log.info("******* " + propertySource.getName() + " *******");
      String[] propertyNames = propertySource.getPropertyNames();
      Arrays.sort(propertyNames);
      for (String propertyName : propertyNames) {
        String resolvedProperty = environment.getProperty(propertyName);
        String sourceProperty = propertySource.getProperty(propertyName).toString();
        if(resolvedProperty.equals(sourceProperty)) {
          log.info("{}={}", propertyName, resolvedProperty);
        }else {
          log.info("{}={} OVERRIDDEN to {}", propertyName, sourceProperty, resolvedProperty);
        }
      }
    }
  }

  private List<EnumerablePropertySource> findPropertiesPropertySources() {
    List<EnumerablePropertySource> propertiesPropertySources = new LinkedList<>();
    for (PropertySource<?> propertySource : environment.getPropertySources()) {
      if (propertySource instanceof EnumerablePropertySource) {
        propertiesPropertySources.add((EnumerablePropertySource) propertySource);
      }
    }
    return propertiesPropertySources;
  }
}