There are number of ways you can externalize your configuration properties in application so that you can work in different environment. You can use properties files, YAML files, environment variables, and command-line arguments to externalize configuration. Property values can be injected directly into your beans by using the @Value
annotation but that is very tedious and cumbersome process , especially if you are working with multiple properties or your data is hierarchical in nature.
Type-safe Configuration Properties
Spring gives you another alternative option so that you can use those properties in Spring Bean fashion. As shown in below example.
Implementation: –
@Configuration @ConfigurationProperties(prefix = "db") public class ApplicationConfig { private String className; private String name; private int port; private String userName; private String password; //setter/getters }
The above POJO class can be defined in the following properties
#Simple Properties db.className=com.mysql.jdbc.Driver db.name=schooldb db.port=7678 db.userName=schoolmaster db.password=hispassword
Getters and setters are usually mandatory, since binding is through standard Java Beans property descriptors, just like in Spring MVC. A setter may be omitted in the following cases:
- Maps, as long as they are initialized, need a getter but not necessarily a setter, since they can be mutated by the binder.
- Collections and arrays can be accessed either through an index (typically with YAML) or by using a single comma-separated value (properties). In the latter case, a setter is mandatory. We recommend to always add a setter for such types. If you initialize a collection, make sure it is not immutable (as in the preceding example).
- If nested POJO properties are initialized (like the
Security
field in the preceding example), a setter is not required. If you want the binder to create the instance on the fly by using its default constructor, you need a setter.
There could be lots of way to implement ApplicationConfig but below is the one which we have followed. We have created one simple Rest Controller and trying to access configuration properties. i.e.
@RestController @RequestMapping("/api") public class MyController { @Autowired private ApplicationConfig applicationConfig; @GetMapping("/config") public String getMethod() { String values = "ClassName:-" + applicationConfig.getClassName() + ", Database - " + applicationConfig.getDb() + ", Port: - " + applicationConfig.getPort() + ", User Name: - " + applicationConfig.getUserName() + ", Password: - " + applicationConfig.getPassword(); return "Hello- " + values; } }
And if you hit this api the outcome will be something like below image.

Third-party Configuration
Using @ConfigurationProperties
to annotate a class, as well as we can also use it on public @Bean
methods. Like below
@Configuration public class ApplicationConfig { @ConfigurationProperties(prefix = "another") @Bean public MyBean getMyBean() { return new MyBean(); } }
And the same properties can be declared in property file as below.
another.value1=value1 another.value2=value2
And some where in your other class. MyBeam can be injected and used like below.
@Autowired private MyBean myBean; @GetMapping("/app-config") public String getApplicationConfig() { String values = "Value1:-" + myBean.getValue1() + ", Value2 - " + myBean.getValue1(); return "Hello- " + values; }
And if you hit this api, you will get the result like.

Relaxed Binding
Spring Boot uses some relaxed rules for binding Environment
properties to @ConfigurationProperties
beans, so there does not need to be an exact match between the Environment
property name and the bean property name. Common examples where this is useful include dash-separated environment properties (for example, context-path
binds to contextPath
), and capitalized environment properties (for example, PORT
binds to port
).
For example, consider the following @ConfigurationProperties
class:
@Configuration @ConfigurationProperties(prefix = "db") public class ApplicationConfig { private String className; private String name; private int port; private String userName; private String password; //setter/getters }
In the above example, the following properties names can all be used:
Property |
db.userName |
db.user_name |
db.user-name etc |
Merging Complex Types
You may have List of some type, example below.
@ConfigurationProperties("myprop") public class MyBeanProperties { private final java.util.List<MyBean> list = new ArrayList<MyBean>(); public java.util.List<MyBean> getList() { return list; } }
Consider the following configuration for above code
myprop: list: - value1: my name value2: my description
Since we have list in our class. So to have multiple values MyBean lets have below values in yml file
myprop: list: - value1: my name1 value2: my description1 - value1: my name 2 value2: my description 2
Same goes for Map like below.
@Configuration @ConfigurationProperties("myprop") public class MyBeanProperties { private final Map<String, MyBean> beanMap = new HashMap<>(); public Map<String, MyBean> getBeanMap() { return beanMap; } }
And below code will go in yml file
mymapprop: beanMap: key1: value1: my name1 value2: my description1 key2: value1: my name2 value2: my description2
Hope this must have cleared your some of doubts about @ConfigurationProperties.
The above code can be found in Github