propertysource not could spring

propertysource - spring boot could not resolve placeholder in value



¿Puede @PropertySources ser elegido por el perfil de Spring? (4)

Agregue la @PropertySource de @PropertySource en una clase interna estática. Desafortunadamente, debe especificar todas las fuentes de propiedad juntas, lo que significa crear un perfil "predeterminado" como alternativa a "anular".

@Configuration public class MyConfiguration { @Configuration @Profile("default") @PropertySource("classpath:defaults.properties") static class Defaults { } @Configuration @Profile("override") @PropertySource({"classpath:defaults.properties", "classpath:overrides.properties"}) static class Overrides { // nothing needed here if you are only overriding property values } @Autowired private Environment environment; @Bean public Bean bean() { ... // this.environment.getRequiredProperty("foo"); ... } }

Tengo un Spring 3.1 @Configuration que necesita una propiedad foo para construir un bean. La propiedad se define en defaults.properties pero puede ser anulada por la propiedad en overrides.properties si la aplicación tiene un perfil de Spring de override activo.

Sin la anulación, el código se vería así y funcionaría ...

@Configuration @PropertySource("classpath:defaults.properties") public class MyConfiguration { @Autowired private Environment environment; @Bean public Bean bean() { ... // this.environment.getRequiredProperty("foo"); ... } }

Me gustaría un @PropertySource para classpath:overrides.properties contingente en @Profile("overrides") . ¿Alguien tiene alguna idea sobre cómo se podría lograr esto? Algunas de las opciones que he considerado son una @Configuration duplicada, pero eso violaría DRY o la manipulación programática de ConfigurableEnvironment , pero no estoy seguro de dónde iría la llamada a environment.getPropertySources.addFirst() .

Colocar lo siguiente en una configuración XML funciona si @Value la propiedad directamente con @Value , pero no cuando uso Environment y el método getRequiredProperty() .

<context:property-placeholder ignore-unresolvable="true" location="classpath:defaults.properties"/> <beans profile="overrides"> <context:property-placeholder ignore-unresolvable="true" order="0" location="classpath:overrides.properties"/> </beans>

Actualizar

Si estás tratando de hacer esto ahora, revisa el soporte YAML de Spring Boot, particularmente la sección ''Usar YAML en lugar de Propiedades''. El soporte de perfil allí haría que esta pregunta sea discutible, pero todavía no @PropertySource soporte de @PropertySource .


No se me ocurre otra @Configuration que la que sugirió Emerson, que es definir este bean en un archivo @Configuration separado con una anotación @Profile :

@Configuration @Profile("override") @PropertySource("classpath:override.properties") public class OverriddenConfig { @Autowired private Environment environment; @Bean public Bean bean() { //if.. } }


Tu puedes hacer:

<context:property-placeholder location="classpath:${spring.profiles.active}.properties" />

Editar: si necesita algo más avanzado, puede registrar sus PropertySources al inicio de la aplicación.

web.xml

<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.xxx.core.spring.properties.PropertySourcesApplicationContextInitializer</param-value> </context-param>

archivo que creas:

public class PropertySourcesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { private static final Logger LOGGER = LoggerFactory.getLogger(PropertySourcesApplicationContextInitializer.class); @Override public void initialize(ConfigurableApplicationContext applicationContext) { LOGGER.info("Adding some additional property sources"); String[] profiles = applicationContext.getEnvironment().getActiveProfiles() // ... Add property sources according to selected spring profile // (note there already are some property sources registered, system properties etc) applicationContext.getEnvironment().getPropertySources().addLast(myPropertySource); } }

Una vez que lo haya hecho, solo tiene que agregar en su contexto:

<context:property-placeholder/>

Realmente no puedo responder a su pregunta sobre varios perfiles, pero supongo que los activa en un inicializador así, y puede registrar los elementos apropiados de PropertySource durante las activaciones de perfil.


Nota: Esta respuesta proporciona una solución alternativa al uso de archivos de propiedades con @PropertySource . Seguí esta ruta porque era demasiado engorroso tratar de trabajar con varios archivos de propiedades que pueden tener anulaciones al tiempo que se evita el código repetitivo.

Cree una interfaz POJO para cada conjunto relacionado de propiedades para definir sus nombres y tipos.

public interface DataSourceProperties { String driverClassName(); String url(); String user(); String password(); }

Implementar para devolver los valores predeterminados.

public class DefaultDataSourceProperties implements DataSourceProperties { public String driverClassName() { return "com.mysql.jdbc.Driver"; } ... }

Subclase para cada perfil (por ejemplo, desarrollo, producción) y anula cualquier valor que difiera del predeterminado. Esto requiere un conjunto de perfiles mutuamente exclusivos, pero puede agregar fácilmente "predeterminado" como la alternativa a "anular".

@Profile("production") @Configuration public class ProductionDataSourceProperties extends DefaultDataSourceProperties { // nothing to override as defaults are for production } @Profile("development") @Configuration public class DevelopmentDataSourceProperties extends DefaultDataSourceProperties { public String user() { return "dev"; } public String password() { return "dev"; } }

Finalmente, conecte las configuraciones de las propiedades a otras configuraciones que las necesiten. La ventaja aquí es que no repites ningún código de creación @Bean .

@Configuration public class DataSourceConfig { @Autowired private DataSourceProperties properties; @Bean public DataSource dataSource() { BoneCPDataSource source = new BoneCPDataSource(); source.setJdbcUrl(properties.url()); ... return source; } }

Todavía no estoy convencido de que me quede con esto sobre la configuración manual de archivos de propiedades basados ​​en los perfiles activos en un inicializador de contexto de servlet. Mi idea era que hacer una configuración manual no sería tan fácil para las pruebas unitarias, pero ahora no estoy tan seguro. Realmente prefiero leer los archivos de propiedades en una lista de accesadores de propiedades.