Why Prefer @Bean Over @Component? Avoid Critical Spring Boot Pitfalls
The article explains the fundamental differences between @Component and @Bean in Spring Boot 3.5.0, demonstrates how @Bean provides finer control, solves five common configuration problems, and reveals a subtle proxy‑related bug that causes multiple bean instances when @Component is misused on configuration classes.
In Spring Boot 3.5.0, beans can be defined in three ways: component scanning with annotations such as @Component, explicit declaration with @Bean inside a configuration class, and the legacy XML approach. Scanning automatically registers simple beans, while @Bean offers precise control over creation, initialization, and dependency wiring.
Core Differences
@Componentis a class‑level annotation; any class marked with it (or its specializations like @Service, @Repository, @Controller) is discovered and registered as a bean by the container. @Bean is a method‑level annotation placed inside a class annotated with @Configuration, allowing the method to return a fully configured object.
@Component
public class MyBean {
// ...
} @Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return new MyBean();
}
}Problems Solved by @Bean
Explicit Bean Configuration : When bean creation requires parameters or complex logic that cannot be expressed with simple annotation scanning.
Third‑Party Class Registration : Classes from external libraries (e.g., HikariDataSource) cannot be annotated with @Component, so they are defined with @Bean.
Custom Initialization : Allows conditional logic or custom code inside the method to set up the bean.
Reusability : Centralizes bean creation in configuration classes, making it easier to maintain and test.
Lazy Initialization : Can be combined with @Lazy to defer bean creation and improve startup time.
Configuration Example
@Configuration
public class DataSourceConfig {
@Bean
public DataSource customDataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ddd");
dataSource.setUsername("root");
dataSource.setPassword("xxxooo");
// ...
return dataSource;
}
}Because HikariDataSource cannot be marked with @Component, the @Bean method creates and returns a fully configured instance.
Dependency Injection
With @Component:
@Component
public class UserService {
// field injection (not recommended)
@Resource
private UserRepository userRepository;
// constructor injection (recommended)
private final CommonService commonService;
public UserService(CommonService commonService) {
this.commonService = commonService;
}
}With @Bean:
@Configuration
public class Config {
@Bean
UserService userService(CommonService commonService) {
return new UserService(commonService);
}
}Both approaches also support conditional injection via @ConditionalOnProperty:
@Bean
@ConditionalOnProperty(prefix = "pack.app", name = "enabled", havingValue = "true", matchIfMissing = false)
public UserService userService(CommonService commonService) { }
@Component
@ConditionalOnProperty(prefix = "pack.app", name = "enabled", havingValue = "true", matchIfMissing = false)
public class UserRepository { }Bean Registration Pitfall
If a class is annotated with @Component and also declares @Bean methods, each call to a @Bean method creates a new instance because the class is treated as a regular object. The following output (first image) shows different instances being printed.
When the same class is changed to @Configuration, Spring creates a CGLIB proxy for the configuration class. Calls to @Bean methods are intercepted by BeanMethodInterceptor, which looks up the bean by name in the container and returns the singleton instance. The second image confirms that the same object is returned each time.
Thus, using @Configuration ensures that internal calls to @Bean methods are routed through the container, guaranteeing singleton semantics, whereas using @Component leads to ordinary method calls that instantiate new objects each time.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.
