Spring Boot
@Configuration annotation
Spring Application
Java
Software Development

Why Spring Boot Application class needs to have Configuration annotation?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The Spring Boot application class does not need a separate @Configuration annotation because @SpringBootApplication already includes it. @SpringBootApplication is a composite annotation that combines @Configuration, @EnableAutoConfiguration, and @ComponentScan. If you see @Configuration on the main class alongside @SpringBootApplication, it is redundant — the configuration behavior is already active.

What @SpringBootApplication Contains

java
1// The @SpringBootApplication annotation is defined as:
2@Target(ElementType.TYPE)
3@Retention(RetentionPolicy.RUNTIME)
4@SpringBootConfiguration   // which itself is @Configuration
5@EnableAutoConfiguration
6@ComponentScan
7public @interface SpringBootApplication {
8    // ...
9}
10
11// @SpringBootConfiguration is just @Configuration with a different name:
12@Target(ElementType.TYPE)
13@Retention(RetentionPolicy.RUNTIME)
14@Configuration
15public @interface SpringBootConfiguration {
16    // ...
17}

So @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan. The @Configuration part tells Spring that this class can define @Bean methods.

What @Configuration Does

java
1@Configuration
2public class AppConfig {
3
4    @Bean
5    public DataSource dataSource() {
6        HikariDataSource ds = new HikariDataSource();
7        ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
8        ds.setUsername("root");
9        ds.setPassword("password");
10        return ds;
11    }
12
13    @Bean
14    public UserService userService(DataSource dataSource) {
15        return new UserService(dataSource);
16    }
17}

@Configuration marks a class as a source of bean definitions. Spring processes the class with CGLIB proxying to ensure that @Bean methods return singleton instances — calling dataSource() from within userService() returns the same instance, not a new one.

Why You Do NOT Need Both

java
1// REDUNDANT — @Configuration is already inside @SpringBootApplication
2@SpringBootApplication
3@Configuration  // unnecessary
4public class MyApplication {
5    public static void main(String[] args) {
6        SpringApplication.run(MyApplication.class, args);
7    }
8}
9
10// CORRECT — @SpringBootApplication is sufficient
11@SpringBootApplication
12public class MyApplication {
13    public static void main(String[] args) {
14        SpringApplication.run(MyApplication.class, args);
15    }
16
17    @Bean
18    public RestTemplate restTemplate() {
19        return new RestTemplate();
20    }
21}

The @Bean method works because @SpringBootApplication already includes @Configuration. Adding @Configuration explicitly does no harm but adds confusion.

When to Use Separate @Configuration Classes

java
1// Main application class
2@SpringBootApplication
3public class MyApplication {
4    public static void main(String[] args) {
5        SpringApplication.run(MyApplication.class, args);
6    }
7}
8
9// Separate configuration class for database beans
10@Configuration
11public class DatabaseConfig {
12
13    @Bean
14    public DataSource dataSource() {
15        return DataSourceBuilder.create()
16            .url("jdbc:postgresql://localhost:5432/mydb")
17            .build();
18    }
19
20    @Bean
21    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
22        return new JdbcTemplate(dataSource);
23    }
24}
25
26// Separate configuration class for security
27@Configuration
28@EnableWebSecurity
29public class SecurityConfig {
30
31    @Bean
32    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
33        return http.csrf(c -> c.disable())
34            .authorizeHttpRequests(auth -> auth
35                .requestMatchers("/api/public/**").permitAll()
36                .anyRequest().authenticated())
37            .build();
38    }
39}

Separate @Configuration classes are the standard practice for organizing beans by concern. They are automatically detected by @ComponentScan (included in @SpringBootApplication).

CGLIB Proxying in @Configuration

java
1@Configuration
2public class AppConfig {
3
4    @Bean
5    public ServiceA serviceA() {
6        return new ServiceA(sharedDependency());
7    }
8
9    @Bean
10    public ServiceB serviceB() {
11        return new ServiceB(sharedDependency());
12    }
13
14    @Bean
15    public SharedDependency sharedDependency() {
16        return new SharedDependency();
17    }
18}
19// serviceA and serviceB both get the SAME SharedDependency instance
20// because @Configuration enables CGLIB proxy interception

Without @Configuration (using @Component instead), each call to sharedDependency() creates a new instance. This is the key behavioral difference — @Configuration ensures singleton semantics for inter-bean references.

@Configuration(proxyBeanMethods = false)

java
1// Lite mode — no CGLIB proxy, faster startup
2@Configuration(proxyBeanMethods = false)
3public class LiteConfig {
4
5    @Bean
6    public ServiceA serviceA(SharedDependency dep) {
7        return new ServiceA(dep);  // inject via parameter, not method call
8    }
9
10    @Bean
11    public SharedDependency sharedDependency() {
12        return new SharedDependency();
13    }
14}

Spring Boot 2.2+ introduced proxyBeanMethods = false for faster startup. With this mode, you must inject dependencies through method parameters instead of calling other @Bean methods directly.

Common Pitfalls

  • Adding @Configuration alongside @SpringBootApplication: This is redundant since @SpringBootApplication already includes @Configuration via @SpringBootConfiguration. It compiles and runs but misleads readers into thinking both are required.
  • Using @Component instead of @Configuration for bean definitions: @Component classes do not get CGLIB proxying, so calling one @Bean method from another creates a new instance each time instead of returning the singleton. Use @Configuration for classes with inter-dependent @Bean methods.
  • Putting all beans in the main application class: While technically valid, defining many @Bean methods in the @SpringBootApplication class creates a bloated entry point. Extract beans into focused @Configuration classes organized by concern.
  • Forgetting that @ComponentScan is included: @SpringBootApplication scans the package of the main class and all sub-packages. Placing @Configuration classes outside this package tree means they will not be detected without an explicit @ComponentScan(basePackages = ...).
  • Not understanding proxyBeanMethods = false: In lite mode, calling another @Bean method directly creates a new instance. Dependencies must be injected through method parameters. Mixing lite mode with direct method calls causes subtle singleton violations.

Summary

  • @SpringBootApplication already includes @Configuration — adding both is redundant
  • @Configuration marks a class as a source of @Bean definitions with CGLIB proxy support
  • CGLIB proxying ensures that @Bean method calls return singleton instances
  • Use separate @Configuration classes to organize beans by concern (database, security, messaging)
  • @Configuration(proxyBeanMethods = false) disables CGLIB proxying for faster startup but requires parameter injection
  • @Component classes with @Bean methods do not get singleton inter-bean references — use @Configuration instead

Course illustration
Course illustration

All Rights Reserved.