2015-10-12 7 views
4

Я пытаюсь найти способ регистрации моих свойств приложения (вставляемых в мои бобы через @ConfigurationProperties) до запуска контекста, чтобы я мог видеть, какие именно свойства перед тем, как все компоненты будут инициализированы.Журнал @ConfigurationProperties в SpringBoot перед запуском?

Я попытался создать Listener в ApplicationEnvironmentPreparedEvent, но нет способа получить все свойства, определенные не до получения отдельных свойств по одному.

Есть ли простой способ сделать это? Как сначала инициализировать @ConfigurationProperties и зарегистрировать их содержимое или получить все свойства запуска приложения до создания контекста?

+0

Я не уверен, что я получаю то, что вы пытаетесь сделать. В любом случае, привод может помочь. Существует конечная точка '/ env', в которой перечислены загруженные файлы конфигурации и их содержимое и'/configprops', которые дают вам обзор фактической конфигурации каждого компонента '@ ConfigurationProperties'. Не уверен, что вам нужно, но это будет хорошим началом. –

+0

@ StéphaneNicoll Я пытаюсь записать/отобразить все мои конфиги до обновления контекста. Например, у меня есть JTA beans и т. Д., Которые являются автоконфигурированными при запуске, поэтому, если соединение терпит неудачу, я хочу видеть, какие свойства конфигурации были до инициализации компонента. Это не приложение, поэтому пути контекста не помогают. Кроме того, если весенний контекст не загружается (неверная конфигурация бина, неудачные проверки и т. Д.), Я хочу видеть, какие именно параметры были использованы. –

+0

@ StéphaneNicoll Я посмотрел на блок исполнительных механизмов для JMX-экспонирования реквизитов конфигурации, но, как я подозревал, он извлекает компоненты из контекста приложения, чтобы отображать их значения. Моя проблема заключается в том, что я хочу зарегистрировать эту информацию до обновления контекста; если компонент не работает во время создания экземпляра из-за неполных или неправильных значений конфигурации, я хотел бы посмотреть, что это за значения. Такая же проблема, если я пытаюсь использовать метод @ @ PostConstruct, вызывается после обновления контекста. Я удивлен, что нет весеннего регистратора, чтобы я мог видеть эти значения по мере их набора. –

ответ

4

Свойства приложения можно просмотреть с помощью специального класса, реализующего ApplicationListener, и определить его как один из классов startupup в записи весенних фабрик, чтобы они выполнялись до загрузки приложения. Шаги заключаются в следующем: -

а) Создайте файл с именем spring.factories в ресурсе есть путь к классам ЦСИ \ главная \ Resources \ META-INF \ spring.factories с содержанием -

# Application Listeners 
org.springframework.context.ApplicationListener=demo.CustomConfigListener 

б) Создание пользовательского класс слушателя в вашем Proj как здесь CustomConfigListener

package demo; 

import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; 
import org.springframework.context.ApplicationEvent; 
import org.springframework.context.ApplicationListener; 
import org.springframework.core.env.EnumerablePropertySource; 
import org.springframework.core.env.PropertySource; 


public class CustomConfigListener implements ApplicationListener<ApplicationEvent> { 

    @Override 
    public void onApplicationEvent(ApplicationEvent event) { 
     if (event instanceof ApplicationEnvironmentPreparedEvent) { 
      for(PropertySource<?> source : ((ApplicationEnvironmentPreparedEvent) event).getEnvironment().getPropertySources()){ 
       if(source.getName().equals("applicationConfigurationProperties")){    
        if (source instanceof EnumerablePropertySource) { 
         for(String name : ((EnumerablePropertySource) source).getPropertyNames()){ 
          System.out.println(name+" :: "+ ((EnumerablePropertySource) source).getProperty(name)); 
         } 
        } 
       } 
      }   
     }  
    } 

} 

с) Ваш заказные ConfigurationProperties класс

package demo; 

import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.stereotype.Component; 

@Component 
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "mail") 
public class MailProperties {  
    private String host; 
    private int port; 
    private Smtp smtp;  
    //Getters & Setters 

    public static class Smtp {  
     private boolean auth; 
     private boolean starttlsEnable;  
     //Getters & Setters 
    } 
} 

d) Наконец ваши application.properties

mail.host=localhost 
mail.port=25 
mail.smtp.auth=false 
mail.smtp.starttls-enable=false 
+0

Может упоминаться [Справочное руководство по применению Spring Boot] (http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-boot-application.html#howto-customize-the- контекст среды или приложения)? – LoganMzz

+1

Фактический реализованный код всегда лучше любого краткого справочного руководства с точки зрения ясности – Avis

+1

Спасибо! Ты дал мне то, что мне не хватало. Я решил, что это должен быть «ApplicationEnvironmentPreparedEvent», но не смог понять, как захватить значения с этой точки. Хотя мне кажется странным, что несколько значений свойств повторяются 2 или 3 раза в перечислении, но это достаточно хорошо для моих нужд. Хотя я бы сказал, что ваш шаг 1 является необязательным; Я могу создать экземпляр, добавляя Listener через 'SpringApplication.addListener()'. –

1

В продолжении к ответу @Avis', я понял, что фрагмент не содержит никакого арга командной строки, и т.д., поэтому я обновил немного его концепцию. Я присоединяю свой класс регистратора, если он имеет значение для тех, кто приземляется на этот вопрос в будущем.

public class ConfigurationLogger implements ApplicationListener<ApplicationEvent> { 
    // slf4j logger 
    private static final Logger logger = LoggerFactory.getLogger(ConfigurationLogger.class); 

    // used to sanitize any password sensitive keys (copied from Spring Boot's Sanitizer() class 
    private Sanitizer sanitizer = new Sanitizer(); 

    // store the config keys in a sorted map 
    private Map<String, Object> configurationProperties = new TreeMap<>(); 


    /** 
    * Trigger upon all events during startup. Both ApplicatoinEnvironmentPrepareEvent and 
    * ApplicationPreparedEvent need access to the same configurationProperties object. Could 
    * have done this through separate events, both extending an abstract base class with a static 
    * hash map, but not worth the effort. Instead have the same class listen for all events, and 
    * delegate to the appropriate method. 
    */ 
    @Override 
    public void onApplicationEvent(ApplicationEvent event) { 
     if (event instanceof ApplicationEnvironmentPreparedEvent) { 
      // store the values 
      onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event); 
     }else if(event instanceof ApplicationPreparedEvent){ 
      // display the values 
      logConfigurationProperties((ApplicationPreparedEvent)event); 
     } 
    } 

    /** 
    * Store the properties in the hash map for logging once all property sources have been read 
    * 
    * @param event 
    */ 
    private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) { 
     for (PropertySource<?> source : event.getEnvironment().getPropertySources()) { 
      if (source instanceof EnumerablePropertySource) { 
       for (String key : ((EnumerablePropertySource) source).getPropertyNames()) { 
        Object value = ((EnumerablePropertySource) source).getProperty(key); 
        if (!configurationProperties.containsKey(key)) { 
         configurationProperties.put(key, sanitizer.sanitize(key, value)); 
        } 
       } 
      } 
     } 
    } 

    /** 
    * Print all the config properties to the logger 
    */ 
    private void logConfigurationProperties(ApplicationPreparedEvent event) { 
     logger.debug("Application started with following parameters: "); 
     for(Map.Entry<String, Object> entry : configurationProperties.entrySet()){ 
      logger.debug("{} :: {}", entry.getKey(), entry.getValue()); 
     } 

    } 
} 

И слушатель инициализируется в главном классе SpringApplication:

@SpringBootApplication 
public class Application{ 
    public static void main(String[] args) { 
     SpringApplication app = new SpringApplication(Application.class); 
     app.setShowBanner(false); 
     // add configuration properties logger 
     app.addListeners(new ConfigurationLogger()); 
     app.run(args); 
    } 
} 
Смежные вопросы