Spring Boot y múltiples archivos de configuración externa

Tengo varios archivos de propiedades que quiero cargar desde classpath. Hay un conjunto predeterminado en /src/main/resources que es parte de myapp.jar . Mi springcontext espera que los archivos estén en classpath. es decir

   

También necesito la opción de anular estas propiedades con un conjunto externo. Tengo una carpeta de configuración externa en cwd . Según la carpeta de configuración de doc de inicio de spring debe estar en classpath. Pero no está claro desde el documento si solo anula las applicaiton.properties de applicaiton.properties desde allí o todas las propiedades en config.

Cuando lo probé, solo application.properties se recogió y el rest de las propiedades todavía se recogen desde /src/main/resources . He intentado suministrarlos como una lista separada por comas a spring.config.location pero el conjunto predeterminado aún no se ha anulado.

¿Cómo puedo hacer que múltiples archivos de configuración externa anulen los predeterminados?

Como solución alternativa, actualmente uso app.config.location (propiedad específica de la aplicación) que proporciono a través de la línea de comandos. es decir

 java -jar myapp.jar app.config.location=file:./config 

y cambié mi applicationcontext para

  

Y así es como hago la separación entre file y classpath al cargar la aplicación.
EDICIONES:

 //psuedo code if (StringUtils.isBlank(app.config.location)) { System.setProperty(APP_CONFIG_LOCATION, "classpath:"); } 

Realmente me gustaría no utilizar la solución anterior y tener el resorte anular todos los archivos de configuración externos en el classpath como lo hace para el archivo application.properties .

Cuando se utiliza Spring Boot, las propiedades se cargan en el siguiente orden (consulte Configuración externa en la guía de referencia Spring Boot).

  1. Argumentos de línea de comando.
  2. Propiedades del sistema Java (System.getProperties ()).
  3. Variables de entorno del sistema operativo.
  4. Atributos JNDI de java: comp / env
  5. Un RandomValuePropertySource que solo tiene propiedades al azar. *.
  6. Propiedades de aplicación fuera de su jar empaquetado (application.properties incluyendo YAML y variantes de perfil).
  7. Propiedades de aplicación empaquetadas dentro de su jar (application.properties incluyendo YAML y variantes de perfil).
  8. Anotaciones @PropertySource en tus clases @Configuration.
  9. Propiedades predeterminadas (especificadas utilizando SpringApplication.setDefaultProperties).

Al resolver propiedades (es decir, @Value("${myprop}") resolución se realiza en el orden inverso (empezando por 9).

Para agregar diferentes archivos, puede usar las propiedades spring.config.location , que toma una lista separada por comas de archivos de propiedades o ubicaciones de archivos (directorios).

 -Dspring.config.location=your/config/dir/ 

El de arriba agregará un directorio que será consultado para application.properties archivos application.properties .

 -Dspring.config.location=classpath:job1.properties,classpath:job2.properties 

Esto agregará el archivo de 2 propiedades a los archivos que están cargados.

Los archivos y las ubicaciones de configuración predeterminadas se cargan antes que los de la spring.config.location adicionales, lo que significa que este último siempre anulará las propiedades establecidas en las anteriores. (Consulte también esta sección de la Guía de referencia de arranque de spring).

Si spring.config.location contiene directorios (a diferencia de los archivos) deben terminar en / (y se agregarán con los nombres generados desde spring.config.name antes de cargarse). La vía de classpath:,classpath:/config,file:,file:config/ búsqueda por defecto classpath:,classpath:/config,file:,file:config/ siempre se utiliza, independientemente del valor de spring.config.location . De esa manera, puede configurar valores predeterminados para su aplicación en application.properties (o cualquier otro nombre de base que elija con spring.config.name ) y anularlo en tiempo de ejecución con un archivo diferente, manteniendo los valores predeterminados.

Con Spring boot, spring.config.location funciona, solo proporcione archivos de propiedades separados por comas.

mira el código a continuación

 @PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties") public class DBConfig{ @Value("${jdbc.host}") private String jdbcHostName; } } 

uno puede poner la versión predeterminada de jdbc.properties dentro de la aplicación. Las versiones externas se pueden establecer mentira esto.

 java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties 

En función del valor del perfil establecido mediante la propiedad spring.profiles.active, se recuperará el valor de jdbc.host. Entonces cuando (en windows)

 set spring.profiles.active=dev 

jdbc.host tomará valor de jdbc-dev.properties.

para

 set spring.profiles.active=default 

jdbc.host tomará valor de jdbc.properties.

Eche un vistazo al PropertyPlaceholderConfigurer, me parece más claro de usar que la anotación.

p.ej

 @Configuration public class PropertiesConfiguration { @Bean public PropertyPlaceholderConfigurer properties() { final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); // ppc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreResourceNotFound(true); final List resourceLst = new ArrayList(); resourceLst.add(new ClassPathResource("myapp_base.properties")); resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie")); resourceLst.add(new ClassPathResource("myapp_test.properties")); resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging. ppc.setLocations(resourceLst.toArray(new Resource[]{})); return ppc; } 

Acabo de tener un problema similar y finalmente descubrí la causa: el archivo application.properties tenía los atributos de propiedad y rwx incorrectos. Entonces, cuando tomcat comenzó, el archivo application.properties estaba en la ubicación correcta, pero era propiedad de otro usuario:

 $ chmod 766 application.properties $ chown tomcat application.properties 

Yo tuve el mismo problema. Quería tener la capacidad de sobrescribir un archivo de configuración interno al inicio con un archivo externo, similar a la aplicación Spring Boot. Detección de propiedades. En mi caso, es un archivo user.properties donde se almacenan los usuarios de mis aplicaciones.

Mis requisitos:

Cargue el archivo desde las siguientes ubicaciones (en este orden)

  1. El camino de clases
  2. Subdirectorio A / config del directorio actual.
  3. El directorio actual
  4. Desde el directorio o una ubicación de archivo dada por un parámetro de línea de comando al inicio

Se me ocurrió la siguiente solución:

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Properties; import static java.util.Arrays.stream; @Configuration public class PropertiesConfig { private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static String PROPERTIES_FILENAME = "user.properties"; @Value("${properties.location:}") private String propertiesLocation; @Bean Properties userProperties() throws IOException { final Resource[] possiblePropertiesResources = { new ClassPathResource(PROPERTIES_FILENAME), new PathResource("config/" + PROPERTIES_FILENAME), new PathResource(PROPERTIES_FILENAME), new PathResource(getCustomPath()) }; // Find the last existing properties location to emulate spring boot application.properties discovery final Resource propertiesResource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties userProperties = new Properties(); userProperties.load(propertiesResource.getInputStream()); LOG.info("Using {} as user resource", propertiesResource); return userProperties; } private String getCustomPath() { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME; } } 

Ahora la aplicación usa el recurso de ruta de clase, pero también busca un recurso en las otras ubicaciones especificadas. El último recurso que existe será recogido y utilizado. Puedo iniciar mi aplicación con java -jar myapp.jar –properties.location = / directory / myproperties.properties para usar una ubicación de propiedades que flote mi bote.

Aquí hay un detalle importante: use un String vacío como valor predeterminado para la propiedad properties.location en la anotación @Value para evitar errores cuando la propiedad no está configurada.

La convención para una ubicación de propiedades es: Usar un directorio o una ruta a un archivo de propiedades como properties.location.

Si desea sobrescribir solo propiedades específicas, se puede usar un Fail de Propiedades con setIgnoreResourceNotFound (verdadero) con el conjunto de recursos establecido como ubicaciones.

Estoy seguro de que esta solución se puede extender para manejar archivos múltiples …

EDITAR

Aquí mi solución para múltiples archivos 🙂 Como antes, esto se puede combinar con un PropertiesFactoryBean.

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Map; import java.util.Properties; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; @Configuration class PropertiesConfig { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static String[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"}; @Value("${properties.location:}") private String propertiesLocation; @Bean Map myProperties() { return stream(PROPERTIES_FILENAMES) .collect(toMap(filename -> filename, this::loadProperties)); } private Properties loadProperties(final String filename) { final Resource[] possiblePropertiesResources = { new ClassPathResource(filename), new PathResource("config/" + filename), new PathResource(filename), new PathResource(getCustomPath(filename)) }; final Resource resource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties properties = new Properties(); try { properties.load(resource.getInputStream()); } catch(final IOException exception) { throw new RuntimeException(exception); } LOG.info("Using {} as user resource", resource); return properties; } private String getCustomPath(final String filename) { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename; } } 

este es un enfoque simple usando arranque de spring

TestClass.java

 @Configuration @Profile("one") @PropertySource("file:/{selected location}/app.properties") public class TestClass { @Autowired Environment env; @Bean public boolean test() { System.out.println(env.getProperty("test.one")); return true; } } 

el contexto de app.properties , en la ubicación seleccionada

 test.one = 1234 

su aplicación de arranque de spring

 @SpringBootApplication public class TestApplication { public static void main(String[] args) { SpringApplication.run(testApplication.class, args); } } 

y el contexto predefinido de application.properties

 spring.profiles.active = one 

puede escribir tantas clases de configuración como desee y habilitarlas / deshabilitarlas simplemente configurando spring.profiles.active = el nombre / nombres del perfil {separados por comas}

como puede ver, la bota de spring es genial, solo necesita familiarizarse con ella, vale la pena mencionar que también puede usar @Value en sus campos

 @Value("${test.one}") String str; 

Spring Boots nos permite escribir diferentes perfiles para escribir en diferentes entornos, por ejemplo, podemos tener archivos de propiedades separados para producción, qa y entornos locales

El archivo application-local.properties con configuraciones según mi máquina local es

 spring.profiles.active=local spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=users spring.data.mongodb.username=humble_freak spring.data.mongodb.password=freakone spring.rabbitmq.host=localhost spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.port=5672 rabbitmq.publish=true 

Del mismo modo, podemos escribir application-prod.properties y application-qa.properties tantos archivos de propiedades como queramos

luego escriba algunos scripts para iniciar la aplicación para diferentes entornos, por ejemplo

 mvn spring-boot:run -Drun.profiles=local mvn spring-boot:run -Drun.profiles=qa mvn spring-boot:run -Drun.profiles=prod 

He encontrado que este es un patrón útil a seguir:

 @RunWith(SpringRunner) @SpringBootTest(classes = [ TestConfiguration, MyApplication ], properties = [ "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant" ,"debug=true", "trace=true" ] ) 

Aquí anulamos el uso de “application.yml” para usar “application-MyTest_LowerImportance.yml” y también “application-MyTest_MostImportant.yml”
(Spring también buscará archivos .properties)

También se incluyen como bonificación extra las configuraciones de depuración y rastreo, en una línea separada para que pueda comentarlas si es necesario;]

La depuración / rastreo es increíblemente útil ya que Spring vaciará los nombres de todos los archivos que carga y los que intenta cargar.
Verá líneas como esta en la consola en tiempo de ejecución:

 TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.properties' (file:./config/application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.xml' (file:./config/application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.yml' (file:./config/application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.yaml' (file:./config/application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.properties' (file:./config/application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.xml' (file:./config/application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.yml' (file:./config/application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.yaml' (file:./config/application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.properties' (file:./application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.xml' (file:./application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.yml' (file:./application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.yaml' (file:./application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.properties' (file:./application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.xml' (file:./application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.yml' (file:./application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.yaml' (file:./application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.xml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.xml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.xml' resource not found DEBUG 93941 --- [ main] osbccConfigFileApplicationListener : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml' (classpath:/application-MyTest_MostImportant.yml) TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.xml' resource not found DEBUG 93941 --- [ main] osbccConfigFileApplicationListener : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml' (classpath:/application-MyTest_LowerImportance.yml) TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant-test.properties' (file:./config/application-MyTest_MostImportant-test.properties) resource not found 

Spring boot 1.X y Spring Boot 2.X no proporcionan las mismas opciones y el mismo comportamiento sobre la Externalized Configuration .

La muy buena respuesta de M. Deinum se refiere a las especificaciones de Spring Boot 1.
Voy a actualizar para Spring Boot 2 aquí.

Fuentes de propiedades del entorno y orden

Spring Boot 2 usa una orden PropertySource muy particular que está diseñada para permitir una anulación de valores sensible. Las propiedades se consideran en el siguiente orden:

  • Propiedades de configuraciones globales de Devtools en su directorio de inicio (~ / .spring-boot-devtools.properties cuando devtools está activo).

  • Anotaciones de @TestPropertySource en tus pruebas.

  • @SpringBootTest#properties atributo de anotación de @SpringBootTest#properties en sus pruebas. Argumentos de línea de comando.

  • Propiedades de SPRING_APPLICATION_JSON (JSON en línea incrustado en una variable de entorno o propiedad del sistema).

  • Parámetros de inicio ServletConfig .

  • Parámetros de inicialización ServletContext .

  • Atributos JNDI de java:comp/env .

  • Propiedades del sistema Java ( System.getProperties() ).

  • Variables de entorno del sistema operativo.

  • Un RandomValuePropertySource que tiene propiedades solo al azar. *.

  • Propiedades de la aplicación específicas del perfil fuera de su paquete empaquetado ( application-{profile}.properties y variantes de YAML).

  • Propiedades de aplicación específicas del perfil empaquetadas dentro de su jar ( application-{profile}.properties y variantes de YAML).

  • Propiedades de aplicación fuera de su jar empaquetado ( application.properties y variantes de YAML).

  • Propiedades de aplicación empaquetadas dentro de su jar ( application.properties y variantes de YAML).

  • Anotaciones @PropertySource en tus clases @Configuration . Propiedades predeterminadas (especificadas al establecer SpringApplication.setDefaultProperties ).

Para especificar archivos de propiedades externas, estas opciones deberían interesarle:

  • Propiedades de la aplicación específicas del perfil fuera de su paquete empaquetado ( application-{profile}.properties y variantes de YAML).

  • Propiedades de aplicación fuera de su jar empaquetado ( application.properties y variantes de YAML).

  • Anotaciones @PropertySource en tus clases @Configuration . Propiedades predeterminadas (especificadas al establecer SpringApplication.setDefaultProperties ).

Puede usar solo una de estas 3 opciones o combinarlas de acuerdo con sus requisitos.
Por ejemplo, para casos muy simples que usan solo propiedades específicas del perfil es suficiente, pero en otros casos es posible que desee utilizar propiedades específicas del perfil, propiedades predeterminadas y @PropertySource .

Ubicaciones predeterminadas para archivos application.properties

Acerca de application.properties archivos application.properties (y variante), de forma predeterminada Spring los carga y agrega sus propiedades en el entorno a partir de estos en el siguiente orden:

  • Subdirectorio A / config del directorio actual

  • El directorio actual

  • Un paquete classpath / config

  • La raíz del classpath

Las prioridades más altas son tan literalmente:
classpath:/,classpath:/config/,file:./,file:./config/ .

¿Cómo usar archivos de propiedades con nombres específicos?

Las ubicaciones predeterminadas no siempre son suficientes: las ubicaciones predeterminadas como el nombre de archivo predeterminado ( application.properties ) pueden no ser adecuadas. Además, como en la pregunta OP, puede que necesite especificar varios archivos de configuración distintos de application.properties (y variante).
Entonces spring.config.name no será suficiente.

En este caso, debe proporcionar una ubicación explícita utilizando la propiedad de entorno spring.config.location (que es una lista de ubicaciones de directorios o rutas de archivos separadas por comas).
Ser libre sobre el patrón de nombres de archivos favorece la lista de rutas de archivos sobre la lista de directorios. De esa manera es la más detallada, pero también es la forma de especificar muy finamente nuestros archivos de configuración.

spring.config.location ahora reemplaza las ubicaciones predeterminadas en lugar de agregarlas

Además, en Spring Boot 1, el argumento spring.config.location agrega ubicaciones especificadas en el entorno de Spring.
Pero desde Spring Boot 2, spring.config.location reemplaza las ubicaciones predeterminadas utilizadas por Spring por las ubicaciones especificadas en el entorno Spring como se indica en la documentación .

Cuando las ubicaciones de configuración personalizada se configuran mediante spring.config.location , reemplazan las ubicaciones predeterminadas. Por ejemplo, si spring.config.location está configurado con el valor classpath:/custom-config/ , file:./custom-config/ , el orden de búsqueda es el siguiente:

  1. file:./custom-config/

  2. classpath:custom-config/

spring.config.location es ahora una forma de asegurarse de que cualquier archivo application.properties debe especificarse explícitamente.
Para los archivos JAR que no se supone que deben empaquetar archivos application.properties , es bastante agradable.

Para mantener el antiguo comportamiento de spring.config.location al usar Spring Boot 2, puede usar la nueva propiedad spring.config.additional-location lugar de spring.config.location que aún agrega las ubicaciones según lo indicado en la documentación :

Alternativamente, cuando las ubicaciones de configuración personalizada se configuran mediante spring.config.additional-location , se usan además de las ubicaciones predeterminadas.


En la práctica

Entonces, supongamos que, como en la pregunta OP, tiene 2 archivos de propiedades externas para especificar y 1 archivo de propiedades incluido en el archivo uber.

Para usar solo los archivos de configuración que especificó:

 -Dspring.config.location=classpath:job1.properties,classpath:job2.properties,classpath:/applications.properties 

Para agregar archivos de configuración a estos en las ubicaciones predeterminadas:

 -Dspring.config.additional-location=classpath:job1.properties,classpath:job2.properties 

classpath:/applications.properties no es necesario porque las ubicaciones predeterminadas tienen eso.

Una versión modificada de la solución @mxsb que nos permite definir múltiples archivos y en mi caso estos son archivos yml.

En mi aplicación-dev.yml, agregué esta configuración que me permite inyectar todo el yml que tiene -dev.yml en ellos. Esta puede ser una lista de archivos específicos también. “classpath: /test/test.yml,classpath: /test2/test.yml”

 application: properties: locations: "classpath*:/**/*-dev.yml" 

Esto ayuda a obtener un mapa de propiedades.

 @Configuration public class PropertiesConfig { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); @Value("${application.properties.locations}") private String[] locations; @Autowired private ResourceLoader rl; @Bean Map myProperties() { return stream(locations) .collect(toMap(filename -> filename, this::loadProperties)); } private Properties loadProperties(final String filename) { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); try { final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename); final Properties properties = new Properties(); stream(possiblePropertiesResources) .filter(Resource::exists) .map(resource1 -> { try { return loader.load(resource1.getFilename(), resource1); } catch (IOException e) { throw new RuntimeException(e); } }).flatMap(l -> l.stream()) .forEach(propertySource -> { Map source = ((MapPropertySource) propertySource).getSource(); properties.putAll(source); }); return properties; } catch (IOException e) { throw new RuntimeException(e); } } } 

Sin embargo, si, como en mi caso, quisiera tener que dividir los archivos yml para cada perfil y cargarlos e inyectarlos directamente en la configuración del resorte antes de la inicialización de los beans.

 config - application.yml - application-dev.yml - application-prod.yml management - management-dev.yml - management-prod.yml 

… entiendes la idea

El componente es ligeramente diferente

 @Component public class PropertiesConfigurer extends PropertySourcesPlaceholderConfigurer implements EnvironmentAware, InitializingBean { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfigurer.class); private String[] locations; @Autowired private ResourceLoader rl; private Environment environment; @Override public void setEnvironment(Environment environment) { // save off Environment for later use this.environment = environment; super.setEnvironment(environment); } @Override public void afterPropertiesSet() throws Exception { // Copy property sources to Environment MutablePropertySources envPropSources = ((ConfigurableEnvironment) environment).getPropertySources(); envPropSources.forEach(propertySource -> { if (propertySource.containsProperty("application.properties.locations")) { locations = ((String) propertySource.getProperty("application.properties.locations")).split(","); stream(locations).forEach(filename -> loadProperties(filename).forEach(source ->{ envPropSources.addFirst(source); })); } }); } private List loadProperties(final String filename) { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); try { final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename); final Properties properties = new Properties(); return stream(possiblePropertiesResources) .filter(Resource::exists) .map(resource1 -> { try { return loader.load(resource1.getFilename(), resource1); } catch (IOException e) { throw new RuntimeException(e); } }).flatMap(l -> l.stream()) .collect(Collectors.toList()); } catch (IOException e) { throw new RuntimeException(e); } } 

}

Me encontré con muchos problemas al tratar de resolver esto. He aquí mi arreglo,

Dev Env: Windows 10, Java: 1.8.0_25, Spring Boot: 2.0.3.RELEASE, Spring: 5.0.7.RELEASE

Lo que encontré es que la spring se está apegando al concepto “Valores predeterminados razonables para la configuración”. En qué se traduce esto es que debe tener todos sus archivos de propiedad como parte de su archivo war. Una vez allí, puede anularlos usando la propiedad de línea de comando “–spring.config.additional-location” para apuntar a los archivos de propiedades externas. Pero esto NO FUNCIONARÁ si los archivos de propiedad no son parte del archivo war original.

Código de demostración: https://github.com/gselvara/spring-boot-property-demo/tree/master