2016-06-17 2 views
4

Я занимаюсь созданием библиотеки, которая обеспечивает унаследованную конфигурацию для приложений, которые используют нашу установку Spring Cloud Config/Eureka. Идея состоит в том, чтобы доставить эту конфигурацию в качестве пользовательского стартера с небольшим или отсутствующим шаблоном, связанным с весной, в отдельных приложениях для микросервисов.Как управлять свойствами бутстрапа весеннего облака в общей библиотеке?

На данный момент большая часть общей конфигурации, которую я хочу разместить в этой библиотеке, состоит из материала в bootstrap.yml. Я хотел бы предоставить bootstrap.yml в своем обычном стартере, но приложения, использующие библиотеку, по-прежнему должны иметь возможность предоставлять свои собственные bootstrap.yml, даже если они могут правильно установить их spring.application.name.

Из-за того, что bootstrap.yml загружен из пути к классам, Spring, похоже, игнорирует тот, что находится в общей библиотеке, если приложение имеет свой собственный bootstrap.yml. Я даже не могу использовать ApplicationContextInitializer для настройки среды из-за специального способа, с помощью которого загрузочный контекст обрабатывает ApplicationContextInitializers.

Есть ли у кого-нибудь рекомендации по подходу, который будет работать здесь? Я хочу предоставить вставку lib, которая заставляет нашу конфигурацию загрузочного бутстрапа работать без дублирования шаблона bootstrap.yml во всех наших проектах.

+3

Я не думаю, что вы могли бы сделать это с самого bootstrap.yml, но вы можете подключить в загрузочный механизм и заполнить источник свойств по умолчанию. – spencergibb

+0

Почему ямльский файл? Вы можете создавать Java-конфигурации. Это было бы проще распространить. –

+0

Конечно, java будет проще распространять. Тем не менее, мне нужно будет сделать большое количество настроек, чтобы выполнить то, что можно сделать очень легко с помощью yaml. Просто предоставление некоторого javaconfig для отключения весенней облачной шины под определенным профилем, например, довольно сложно с точки зрения конфигурации по соглашению, но это можно сделать в yaml с простой spring.cloud.bus.enabled = false. Просто для того, чтобы предоставить стандартную дефолту eureka по умолчанию, я смотрю на настройку компонентов, которые в противном случае получат выгоду от autoconfig. – shazbot

ответ

1

Я смог найти решение этого вопроса. Целями этого решения являются:

  • Загрузить значения из файла yaml в общей библиотеке.
  • Разрешить приложениям, использующим библиотеку, ввести свой собственный bootstrap.yml, который также загружается в среду.
  • Значения в bootstrap.yml должны переопределять значения в общем ямле.

Основная задача состоит в том, чтобы ввести некоторый код в соответствующую точку жизненного цикла приложения. В частности, нам нужно сделать это после того, как bootstrap.yml PropertySource добавлен в среду (чтобы мы могли вставлять наш собственный PropertySource в правильном порядке относительно него), но также перед тем, как приложение начнет настраивать bean-компоненты (поскольку наши значения параметров конфигурации поведение).

Решение, которое я нашел в том, чтобы использовать пользовательские EnvironmentPostProcessor

public class CloudyConfigEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { 

    private YamlPropertySourceLoader loader; 

    public CloudyConfigEnvironmentPostProcessor() { 
     loader = new YamlPropertySourceLoader(); 
    } 

    @Override 
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) { 
     //ensure that the bootstrap file is only loaded in the bootstrap context 
     if (env.getPropertySources().contains("bootstrap")) { 
      //Each document in the multi-document yaml must be loaded separately. 
      //Start by loading the no-profile configs... 
      loadProfile("cloudy-bootstrap", env, null); 
      //Then loop through the active profiles and load them. 
      for (String profile: env.getActiveProfiles()) { 
       loadProfile("cloudy-bootstrap", env, profile); 
      } 
     } 
    } 

    private void loadProfile(String prefix, ConfigurableEnvironment env, String profile) { 
     try { 
      PropertySource<?> propertySource = loader.load(prefix + (profile != null ? "-" + profile: ""), new ClassPathResource(prefix + ".yml"), profile); 
      //propertySource will be null if the profile isn't represented in the yml, so skip it if this is the case. 
      if (propertySource != null) { 
       //add PropertySource after the "applicationConfigurationProperties" source to allow the default yml to override these. 
       env.getPropertySources().addAfter("applicationConfigurationProperties", propertySource); 
      } 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 
    } 

    @Override 
    public int getOrder() { 
     //must go after ConfigFileApplicationListener 
     return Ordered.HIGHEST_PRECEDENCE + 11; 
    } 

} 

Этот обычай EnvironmentPostProcessor может быть введен с помощью META-INF/spring.factories:

#Environment PostProcessors 
org.springframework.boot.env.EnvironmentPostProcessor=\ 
com.mycompany.cloudy.bootstrap.autoconfig.CloudyConfigEnvironmentPostProcessor 

Пару вещей отметить:

  • YamlPropertySourceLoader загружает свойства yaml по профилю, поэтому, если вы используете мульти- document yaml, вам нужно фактически загрузить каждый из них отдельно, включая конфигурации без профиля.
  • ConfigFileApplicationListener - это EnvironmentPostProcessor, ответственный за загрузку bootstrap.yml (или application.yml для обычного контекста) в среду, поэтому, чтобы правильно настроить пользовательские свойства yaml относительно свойств bootstrap.yml, вам нужно заказать заказную программу EnvironmentPostProcessor после ConfigFileApplicationListener.

Редактировать: Мой первоначальный ответ не сработал. Я заменяю его этим, что и есть.

1

Вы можете добавить свойство PropertySource в общую библиотеку к свойствам начальной загрузки, используя ключ org.springframework.cloud.bootstrap.BootstrapConfiguration в файле META-INF/spring.factories.

Например, вы можете создать библиотеку, содержащую следующие:

SRC/основные/Java/COM/например/MYLIB/MyLibConfig.java

package com.example.mylib; 

import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.PropertySource; 

@Configuration 
@PropertySource("classpath:mylib-config.properties") 
public class MyLibConfig { 
} 

SRC/основные/ресурсы /mylib-config.properties

eureka.instance.public=true 
# or whatever... 

SRC/Основной/resour цы/META-INF/spring.factories

org.springframework.cloud.bootstrap.BootstrapConfiguration=com.example.mylib.MyLibConfig 

Подробнее: http://projects.spring.io/spring-cloud/spring-cloud.html#_customizing_the_bootstrap_configuration