Reputation: 14520
I know the default order of spring's properties sources: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html how can i add my own property source with a specific precedence?
@PropertySource
is not enough as it adds new properties with very low priority
Upvotes: 2
Views: 2945
Reputation: 5369
There are plenty of ways to do this; I'll just quote the official documentation:
A
SpringApplication
hasApplicationListener
s andApplicationContextInitializer
s that are used to apply customizations to the context or environment. Spring Boot loads a number of such customizations for use internally fromMETA-INF/spring.factories
. There is more than one way to register additional ones:
- Programmatically per application by calling the
addListeners
andaddInitializers
methods onSpringApplication
before you run it.- Declaratively per application by setting
context.initializer.classes
orcontext.listener.classes
.- Declaratively for all applications by adding a
META-INF/spring.factories
and packaging a jar file that the applications all use as a library.The
SpringApplication
sends some specialApplicationEvents
to the listeners (even some before the context is created), and then registers the listeners for events published by the ApplicationContext as well. See Section 23.4, “Application events and listeners” in the ‘Spring Boot features’ section for a complete list.It is also possible to customize the
Environment
before the application context is refreshed usingEnvironmentPostProcessor
. Each implementation should be registered inMETA-INF/spring.factories
:org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
My way was always to add an ApplicationEnvironmentPreparedEvent listener:
public class IntegrationTestBootstrapApplicationListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 4;
public static final String PROPERTY_SOURCE_NAME = "integrationTestProps";
private int order = DEFAULT_ORDER;
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
if (!environment.getPropertySources().contains(PROPERTY_SOURCE_NAME)) {
Map<String, Object> properties = ...; // generate the values
// use whatever precedence you want - first, last, before, after
environment.getPropertySources().addLast(
new MapPropertySource(PROPERTY_SOURCE_NAME, properties));
}
}
}
But you can just as easily use an initializer:
public class IntegrationTestBootstrapApplicationListener implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final String PROPERTY_SOURCE_NAME = "integrationTestProps";
@Override
public void initialize(final ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> properties = ...; // generate the values
// use whatever precedence you want - first, last, before, after
environment.getPropertySources().addLast(
new MapPropertySource(PROPERTY_SOURCE_NAME, properties));
}
}
Upvotes: 3