Sometimes we need to load a lot of environment variables from application.properties or application.yml to our spring boot project for using and it is not good way if we use traditional way with @Value.
@ConfigurationProperties and Component will help us to convert environment variables to become a spring bean and we can use it everywhere in our project with @Autowired. This is the esiest way to config. Now, let's see the example below
For example we have an application.yml with some environment as below. As you can see the data has 3 attributes are name, amount and price, so we can imagine that there is an object data has 3 attributes.
application.yml
1234
data:name:notebookamount:500price:10.5
So the first thing we should do is create an object class with getter and setter as default. Then we add the annotation @ConfigurationProperties(prefix = "data"), The prefix of the properties that are valid to bind to object. Synonym for prefix, a valid prefix is defined by one or more words separated with dots (e.g. "company.customer.data").
packagecom.springboot.project.configuration.properties.model;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.stereotype.Component;/** prefix = "data" it is mean this object is "data" in application.yaml And name, amount and price are 3 attributes in this object. @Component will make this object become an spring bean and we can use it everywhere with annotation @Autowired */@Component@ConfigurationProperties(prefix="data")publicclassData{privateStringname;privateIntegeramount;privatedoubleprice;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicIntegergetAmount(){returnamount;}publicvoidsetAmount(Integeramount){this.amount=amount;}publicdoublegetPrice(){returnprice;}publicvoidsetPrice(doubleprice){this.price=price;}}
Then we can use it everywhere by using annotation @Autowired
Now, we will start our spring boot service and call api to check the result.
Using @ConfigurationProperties With Other configuration ways#
So there 2 more ways to make environment varialbes becomce spring bean with @ConfigurationProperties.
The first way is using annotation @EnableConfigurationProperties(value = {Data2.class}). We just put this annotation in our main class and put the array of classes that are using ConfigurationProperties. Let's see the Example below
We don't use @Component anymore so our data class will look like this
packagecom.springboot.project.configuration.properties;importcom.springboot.project.configuration.properties.model.Data2;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.context.properties.EnableConfigurationProperties;/** @EnableConfigurationProperties(value = {Data2.class}) value is the Data.class that we define above*/@SpringBootApplication@EnableConfigurationProperties(value={Data2.class})publicclassConfigurationPropertiesApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ConfigurationPropertiesApplication.class,args);}}
Then we can use it everywhere by using annotation @Autowired
The second way is like the way above with no annotation @Component in our Data2.class but we will use the annotation @ConfigurationPropertiesScan(value = {"com.springboot.project.configuration.properties.model"}) the value of this annotation is an array of path to the package that contains our Data.class. So if we have many classes using ConfigurationProperties we can use this way
So our main class we look like as below
ConfigurationPropertiesApplication.java
1 2 3 4 5 6 7 8 91011121314151617181920212223
packagecom.springboot.project.configuration.properties;importcom.springboot.project.configuration.properties.model.Data2;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.context.properties.ConfigurationPropertiesScan;importorg.springframework.boot.context.properties.EnableConfigurationProperties;/** "com.example.workflow.model" is the path to the package that contain Data2.class which is using @ConfigurationProperties*/@SpringBootApplication//@EnableConfigurationProperties(value = {Data2.class})@ConfigurationPropertiesScan(value={"com.springboot.project.configuration.properties.model"})publicclassConfigurationPropertiesApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ConfigurationPropertiesApplication.class,args);}}
Now, let's call api to check the result, you can see it's the same with the first way.
packagecom.springboot.project.configuration.properties;importcom.springboot.project.configuration.properties.model.Data2;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.context.properties.ConfigurationPropertiesScan;importorg.springframework.boot.context.properties.EnableConfigurationProperties;/** "com.example.workflow.model" is the path to the package that contain Data2.class which is using @ConfigurationProperties*/@SpringBootApplication//@EnableConfigurationProperties(value = {Data2.class})@ConfigurationPropertiesScan(value={"com.springboot.project.configuration.properties.model"})publicclassConfigurationPropertiesApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ConfigurationPropertiesApplication.class,args);}}
Finally we can use the Data3.class everywhere with @Autowired and It contains the data of Shipper.class also.
Using @ConfigurationProperties with @Configuration#
We can use @ConfigurationProperties and @Bean to initiate a bean which is loaded from application.yml in configuration classes.
To do it, let's create a Data4.class as below, that does not require us to add any annotation more, just a default java model class.