How to add custom property source to Spring's Environment
From Spring 3.1
The Spring framework added a new way mechanism to bootstrap your application based on the environment it evolves in. The Environment abstraction that is part of version 3.1+ of the framework is well explained in this article. Features provided by the new abstraction if twofold : profiles and property resolution.
Spring allows you to define and load properties really well with the @PropertySource
annotation that you put on your @Configuration
classes. @PropertySource
takes the location of a property file and load all properties to the current spring Environment
. This makes really easy to load a app.properties
file which contains your configuration and also load a app-test.properties
file to override or redefined them.
Custom property source
However, in my case, I had to deal with a legacy configuration source based on a simple TCP/IP protocol and wanted to integrate it with the Environment
concept so that our new applications would be all using this mechanism.
Here's a simple configuration that allows to do it:
@Configuration
public class TcpIpPropertySourceConfig {
@Autowired
private ConfigurableEnvironment env;
@Bean
@Lazy(false)
public TcpIpPropertySource tcpIpPropertySource() {
TcpIpPropertySource tcpIpPropSource = new TcpIpPropertySource();
MutablePropertySources sources = env.getPropertySources();
sources.addFirst(new PropertiesPropertySource("tcp-ip", tcpIpPropSource.getAllProperties()));
}
return tcpIpPropSource;
}
what is going on?
- Your configuration is getting loaded in some way by the spring application context. The context has already an environment configured in it that will get injected with the
@Autowired
annotation. - The
@Bean
definition is also@Lazy(false)
, which will force Spring to create this bean quite early in the cycle. Maybe there are some other ways of doing it that I'm not aware of. Because the bean will be one of the first to be created, it will modify the environment so that other bean creations will then see your custom loaded properties. - The
new PropertiesPropertySource
is added first, but you can really do what you want with the precedence here.
To summarize:
I showed here a simple way to modify your environment's properties based on a custom properties loader. My requirement was based on a TCP/IP property source, but it could also be a JDBC, HTTP or anything you need to interface with.
Written by JP Melanson
Related protips
2 Responses
If you make your TcpIpPropertySource to extend PropertySource<T> you can just add it to the sources.
sources.addFirst( tcpIpPropSource );
You could accomplish the same thing by using the @Order annotation with the @Configuration annotation and setting the value for the @Order annotation to be Ordered.HIGHEST_PRECEDENCE. Then, have TcpIpPropertySourceConfig implement InitializingBean.