In this article, we’ll go through what @Configuration in Spring Boot is and how to use it.
1. What is @Configuration Annotation in Spring Boot
We use @Configuration
in Spring Boot mainly to declare new beans that will be included in the Spring Context. We can inject these beans through @Autowired Annotation wherever we need them. Furthermore, @Configuration
tags this class as a bean in order to be included in the Spring Context.
@Configuration
has 3 attributes:
value
, which allows you to specify the bean name.proxyBeanMethods
, which defaults totrue
.- Lastly,
enforceUniqueMethods
, which defaults totrue
.
We will see later in the examples how and why you might need to change them.
2. Setting Up The Project
First of all, you need to have Java installed, if you do not you can go through these tutorials depending on the OS your machine runs:
- Linux users: Install Java on Linux
- macOs users: Install Java on macOS
- Windows users: Install Java on Windows
For this tutorial, we are using the IntelliJ IDEA Community edition which you can download here.
If you are not using this IDE, you also need to download Maven here.
The next step is to visit Spring initializr and generate a project according to these settings shown in the image:
![Spring Initializr](https://youlearncode.com/wp-content/uploads/2022/10/Screenshot_16-1024x811.png)
After having chosen the above options, press the GENERATE button, and a new spring boot project will be downloaded for you. Then you have to unzip the compressed archive and open the folder with your favorite IDE.
3. Creating the Services
In order to demonstrate how @Configuration works we will create 3 services:
PunctuationService
, a service that provides punctuation marks such as “.” or “?”.LowerCaseWordsService
, a service that provides some lower-case words and hasPunctuationService
as a dependency.- Lastly,
UpperCaseWordsService
, a service that provides some upper-case words and hasPunctuationService
as a dependency.
PunctuationService:
package com.codelearnhub.configurationAnnotation.service; import java.util.Arrays; import java.util.List; public class PunctuationService { private final List<Character> punctuationMarks = Arrays.asList('.', ';', '!', '?'); public List<Character> getAllPunctuationMarks(){ return punctuationMarks; } }
LowerCaseWordsService:
package com.codelearnhub.configurationAnnotation.service; import java.util.Arrays; import java.util.List; public class LowerCaseWordsService { private final PunctuationService punctuationService; private final List<String> words = Arrays.asList("code", "learn", "hub"); public LowerCaseWordsService(PunctuationService punctuationService) { this.punctuationService = punctuationService; } public PunctuationService getPunctuationService() { return punctuationService; } public List<String> getAllWords(){ return words; } }
UpperCaseWordsService:
package com.codelearnhub.configurationAnnotation.service; import java.util.Arrays; import java.util.List; public class UpperCaseWordsService { private final List<String> words = Arrays.asList("CODE", "LEARN", "HUB"); private final PunctuationService punctuationService; public UpperCaseWordsService(PunctuationService punctuationService) { this.punctuationService = punctuationService; } public PunctuationService getPunctuationService() { return punctuationService; } public List<String> getAllWords(){ return words; } }
As you can observe we haven’t added any of the classes to the Spring Context since they do not have any annotation such as @Service
.
4. Creating the Config Class Using @Configuration Annotation
Now it’s time to create the Configuration class and see how we can declare beans through it. Before we begin, let’s explain how the two aforementioned attributes behave.
4.1 proxyBeanMethods Attribute
This attribute specifies if @Bean
annotated methods will use a proxy(more specifically CGLib). Note that setting this attribute to false(also known as @Bean Lite Mode) makes @Configuration
annotation redundant and just @Component annotation would suffice.
The advantage of using a proxy is that whenever we call a @Bean annotated method, the same bean will be returned. However, this comes with some disadvantages:
- Startup time might be slower in comparison to setting this attribute as
false
. Especially when a lot of@Configuration
annotated classes exist. - You cannot declare both the class and any method as final as they need to be subclassed.
4.2 enforceUniqueMethods Attribute
This attribute is exactly what its name indicates; we cannot have two methods of the same.
As a result, overloading cannot be applied to every @Bean
annotated method.
4.3 Using Defaults
The first case is when we do not change the values of proxyBeanMethods
and enforceUniqueMethods
.
package com.codelearnhub.configurationAnnotation.configuration; import com.codelearnhub.configurationAnnotation.service.LowerCaseWordsService; import com.codelearnhub.configurationAnnotation.service.PunctuationService; import com.codelearnhub.configurationAnnotation.service.UpperCaseWordsService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class Config { @Bean public LowerCaseWordsService lowerCase(){ return new LowerCaseWordsService(punctuationService()); } @Bean public UpperCaseWordsService upperCase(){ return new UpperCaseWordsService(punctuationService()); } @Bean public PunctuationService punctuationService(){ return new PunctuationService(); } }
The name of the bean by default matches the name of @Bean annotated method.
Three beans will be created (and the first two beans will use the third) upon startup since we used the @Bean
annotation, even though we didn’t tag the respective classes with an annotation like @Component
or @Service
.
The next step is to test if only one PunctuationService
bean was created; head to ConfigurationAnnotationApplication.java
package com.codelearnhub.configurationAnnotation; import com.codelearnhub.configurationAnnotation.service.LowerCaseWordsService; import com.codelearnhub.configurationAnnotation.service.UpperCaseWordsService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConfigurationAnnotationApplication { public static void main(String[] args) { var context = SpringApplication.run(ConfigurationAnnotationApplication.class, args); var lowerCaseBean = (LowerCaseWordsService) context.getBean("lowerCase"); var upperCaseBean = (UpperCaseWordsService) context.getBean("upperCase"); System.out.printf("Do both punctuation services point to the same object? %b", lowerCaseBean.getPunctuationService() == upperCaseBean.getPunctuationService() ); } }
Let’s explain what we did here:
- We hold the context in a variable
context
. - Then we retrieve the lowerCase bean and UpperCase bean from the application context.
- Then we check if the 2 beans have the same reference.
If you do run the app, you will see that true
will be printed, as we have proxyBeanMethods
set to true
.
4.4 Using proxyBeanMethods as false
Now the only thing that we’ll change is the annotation to
@Configuration(proxyBeanMethods = false)
Now re-run the app and you will see that false
is printed. This means that the second time punctuationService()
method was called, a new bean was created.
4.5 Using enforceUniqueMethods as false:
Now set the @Configuration
annotation to
@Configuration(enforceUniqueMethods = false)
and then add another method:
@Bean public UpperCaseWordsService upperCase(String dummy){ return new UpperCaseWordsService(punctuationService()); }
If you run the app, no exceptions will be thrown. However, if you change the annotation back to @Configuration
(using the defaults) and re-run the app you will get the following error:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: @Configuration class 'Config' contains overloaded @Bean methods with name 'upperCase'. Use unique method names for separate bean definitions (with individual conditions etc) or switch '@Configuration.enforceUniqueMethods' to 'false'. Offending resource: class path resource [com/codelearnhub/configurationAnnotation/configuration/Config.class]
5. Conclusion
By now you should be able to use @Configuration annotation in Spring Boot with or without changing the default attributes. You can find the source code on our GitHub page.