Spring PropertySourcesPlaceholderConfigurer

0

In our previous article about PropertyResolver, we looked into the core algorithm and the APIs involved that helped in resolving property placeholders into actual values.

In this article, we see how PropertySourcesPlaceholderConfigurer can be used to resolve property placeholders in the context file.

Scenario

Test and production environment have separate property files, and based on the environment property, the place holders in the context should be replaced with the actual values.

PropertySourcesPlaceholderConfigurer

Spring provides PropertySourcesPlaceholderConfigurer which resolves the placeholders specified in the spring context file. PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor bean so it gets a chance to modify the application context’s bean definitions even before the beans are instantiated.
All the bean definitions are traversed, and wherever place holders are used they are replaced with actual values. It replaces the placeholders in the below attributes.

  • parent name
  • bean class name
  • factory bean name
  • scope
  • property values
  • constructor’s argument values

Internally, it relies on PropertySourcesPropertyResolver to resolve the place holders.

Context file

In the context file, we add a bean definition for PropertySourcesPlaceholderConfigurer.
The properties file path is specified in the location attribute /org/springframework/context/support/${my_env:test}PropPlaceholder.properties. Note that there is a placeholder ${my_env:test} in the location path so my_env should be set as a system property or in system environment. If it is not set, the default value “test” would be used.

Context file: placeHolderCustomElement.xml

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="prop" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="/org/springframework/context/support/${my_env:test}PropPlaceholder.properties"/>
    </bean>
    <bean id="env" class="java.lang.String">
        <constructor-arg index="0" value="${env}"/>
    </bean>
</beans>

There will be two property files, one for test and the other for production.

prodPlaceholder.properties has

env=prod

testPlaceholder.properties has

env=test

We also have another bean based on String class to test whether we are getting proper place holder values.

Test case

In the below test case, we create the application context based on the above context file.

Since my_env is not set, testPlaceholder.properties will be loaded. The string bean "env" returns value “test”.Next, we set the my_env to prod and refresh the context, this time string bean returns “prod”.

    @Test
    public void definePropertyPlaceholderBean() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/context/support/placeHolderCustomElement.xml");
        assertEquals("test", context.getBean("env"));
        System.setProperty("my_env", "prod");
        context.refresh();
        assertEquals("prod", context.getBean("env"));
    }

In our next article, we will look into the various properties of PropertySourcesPlaceholderConfigurer and the related scenarios.

Custom element

Instead of creating explicitly bean definition for, we can also use the custom element <context:property-placeholder>

<context:property-placeholder location="/org/springframework/context/support/${my_env:test}PropPlaceholder.properties" />

Class diagram

Since PropertySourcesPlaceholderConfigurer modifies the bean definitions so it must be initialized ahead of other post-processor beans. This is done by making it implement the marker interface PriorityOrdered.
In below class diagram, the important structural links are highlighted.

  • PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor as it has to modify the bean definitions.
  • It implements PriorityOrdered as it must be initialized ahead of other beans.
  • It depends on PropertySourcesPropertyResolver to resolve placeholders.
  • It depends on BeanDefinitionVisitor which re-visits the bean definition, traverses through all the bean definitions and resolve the place holders.

 

PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer

 

Share.

Leave A Reply