Why @Configuration + @Bean Overrides @Component in Spring Boot: Deep Dive and Version Differences

A detailed analysis shows that when a class is annotated with both @Configuration/@Bean and @Component, Spring creates only one bean—the one defined by @Configuration/@Bean—overriding the @Component definition, and explains how this behavior changed across Spring and Spring Boot versions.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Why @Configuration + @Bean Overrides @Component in Spring Boot: Deep Dive and Version Differences

Background

During development a class was annotated both with @Configuration/@Bean and @Component, leading to two bean definitions of UserManager with different userName values. The project runs without errors, but it is unclear which bean is injected.

Problem Description

The code snippet shows a @Configuration class defining a @Bean method that returns a UserManager with a non‑null userName, while the same class is also annotated with @Component, which would create a UserManager with a null userName. The question is which instance Spring actually injects.

Spring Boot Version

The project uses Spring Boot 2.0.3.RELEASE and the default bean scope is singleton.

Result Verification

By debugging the constructor calls only the parameterized constructor of UserManager is invoked, indicating that only one bean instance is created. The log shows that the bean definition from @Configuration/@Bean overrides the one from @Component.

2021-10-03 20:37:33.697 INFO 13600 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'userManager' with a different definition: replacing [Generic bean: class [com.lee.qsl.manager.UserManager]; ... with [Root bean: class [null]; ... defined in class path resource [com/lee/qsl/config/UserConfig.class]]

Source Code Analysis

The @Configuration class is processed by ConfigurationClassPostProcessor during component scanning. It creates a ConfigurationClassBeanDefinition that replaces the original ScannedGenericBeanDefinition generated for the @Component annotation. The bean factory then uses the @Configuration/@Bean definition to instantiate UserManager, invoking its parameterized constructor.

img
img

The processing flow involves:

Component scan discovers UserConfig, UserController, and UserManager.

Before @Bean methods are processed, UserManager is registered as a scanned component.

ConfigurationClassPostProcessor parses @Configuration classes, builds ConfigurationClass objects, and registers bean definitions for @Bean methods.

The original bean definition for UserManager is overridden by the one created from @Configuration/@Bean.

img
img

After the recursive processing of configuration classes, the bean definition map contains a single entry for 'userManager' of type ConfigurationClassBeanDefinition, which leads to the creation of the bean defined by @Configuration/@Bean.

Spring Upgrade Optimization

Spring 5.1.2.RELEASE (and Spring Boot 2.1.0) introduced the allowBeanDefinitionOverriding property, allowing developers to control whether bean definitions may be overridden. By default Spring permits overriding, but Spring Boot disables it unless explicitly enabled.

To enable overriding in Spring Boot, add the following to application.properties:

spring.main.allow-bean-definition-overriding=true

This makes the behavior explicit and avoids hidden overrides.

Summary

Spring 5.0.7.RELEASE (used by Spring Boot 2.0.3.RELEASE) supports both @Configuration/@Bean and @Component on the same class, but the @Configuration/@Bean definition overrides the @Component definition during container initialization. Starting with Spring 5.1.2.RELEASE, the framework provides a configurable property allowBeanDefinitionOverriding to let developers decide if such overrides are allowed.

Supplement

The allowBeanDefinitionOverriding flag has existed since Spring 1.2 in DefaultListableBeanFactory (default true). Spring 4.1.2 added the isAllowBeanDefinitionOverriding() method. Spring Boot 2.1.0 introduced its own flag, defaulting to false, which overrides the core Spring default.

ConfigurationComponentSpring BootSpring FrameworkVersion DifferencesBean Overriding
Java Architect Handbook
Written by

Java Architect Handbook

Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.