Last Updated: February 25, 2016
·
59.48K
· jplmelanson

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.

2 Responses
Add your response

If you make your TcpIpPropertySource to extend PropertySource<T> you can just add it to the sources.

sources.addFirst( tcpIpPropSource );

over 1 year ago ·

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.

over 1 year ago ·