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.
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.
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.
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=trueThis 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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
