Blog Spring Boot

Difference between @Bean and @Component

Bean

  • Definition: In Spring, a bean is an object that is instantiated, assembled, and otherwise managed by the Spring IoC (Inversion of Control) container. Beans are the backbone of your application’s configuration and are managed by Spring’s dependency injection features.
  • Creation: Beans can be created in multiple ways:
    • Through XML configuration files (traditional Spring, less common in modern Spring Boot applications).
    • Using Java configuration: by annotating a method with @Bean in a class annotated with @Configuration.
    • Automatically by Spring Boot’s auto-configuration when certain conditions are met, based on classpath contents and other factors.
  • Scope and Customization: Beans allow for advanced configurations, including specifying scope (singleton, prototype, request, session, etc.), lazy initialization, and lifecycle callbacks. They are typically used for more fine-grained control and when specific configurations or lifecycle management are needed.

Component

  • Definition: A component in Spring is a class that is automatically detected and registered as a bean in the Spring container through classpath scanning. Components are a subset of beans.
  • Creation: Components are created by annotating classes with @Component or one of its stereotypes (@Service, @Repository, @Controller, @RestController, etc.). When the application starts, Spring scans the classpath for classes annotated with these stereotypes and automatically instantiates and registers them as beans.
  • Simplicity and Convention: Using components is a more convenient and convention-over-configuration approach. It’s well-suited for defining beans that don’t require special configuration or lifecycle management beyond what’s provided by default.

Key Differences

  • Declaration Method: A bean defined with @Bean annotation is usually declared in a Java configuration class marked with @Configuration, allowing for programmatic construction and configuration. A component, marked with @Component or its derivatives, is automatically detected by Spring’s classpath scanning.
  • Purpose and Usage: @Bean is more versatile for defining beans, especially when creating third-party objects or configuring beans with specific requirements (like external resources). @Component and its stereotypes are more about marking classes as Spring-managed components, simplifying auto-detection and auto-registration.
  • Customization Level: Beans defined with @Bean can be given a custom scope, initialization, and destruction methods directly in the method defining the bean. Components get their configuration from the stereotype annotations and can be further customized with annotations like @Scope or through callback interfaces.

Both @Bean and @Component annotations are used to register/create beans in the Spring Application Context, but they serve this purpose in slightly different ways:

@Bean

  • Used primarily in @Configuration classes.
  • Ideal for explicit registration of beans, particularly when you’re creating instances of third-party classes or when you need specific configurations that are not the default.
  • Allows for programmatic definition of beans, giving you control over bean instantiation and configuration. You can specify bean scope, lifecycle callbacks, and dependencies explicitly.
  • Typically used for beans that require explicit configuration or are not automatically discoverable by Spring’s component scanning.

@Component

  • A stereotype annotation that indicates a class is a Spring-managed component.
  • When you annotate a class with @Component (or with annotations that are meta-annotated with @Component such as @Service, @Repository, @Controller), Spring automatically detects it during classpath scanning and registers it as a bean in the ApplicationContext.
  • Requires less configuration than @Bean-annotated methods. It’s more convention-over-configuration, leveraging Spring’s auto-detection mechanism.
  • Ideal for defining Spring-managed components that are part of your application’s codebase, especially those that don’t require special instantiation logic or configuration.

Real-Time Examples of Advance Bean Configuration in Spring Boot

Certainly! Let’s consider a real-time example involving a connection to a database using Spring Data JPA. In this scenario, we want to define a DataSource bean that Spring Boot can use to manage database connections. This example will illustrate how to explicitly configure a bean using the @Bean annotation within a @Configuration class.

Scenario: Custom DataSource Configuration

Suppose you have a Spring Boot application where you need to connect to a PostgreSQL database. While Spring Boot’s auto-configuration is powerful and can automatically set up a DataSource based on your application.properties or application.yml settings, there might be cases where you need custom configuration for your DataSource that isn’t covered by auto-configuration or requires specific tuning.

First, ensure that you have the necessary dependencies in your pom.xml or build.gradle file. For a Maven project, your pom.xml might include:

Step 1: Add Dependencies

To use Spring Boot’s support for DataSource configuration, as well as to enable the @ConfigurationProperties functionality, you need to include specific dependencies in your pom.xml file. Here’s a breakdown of the dependencies you’ll typically require for a Spring Boot application that connects to a database and utilizes @ConfigurationProperties:

Spring Boot Starter Data JPA

This starter includes Spring Data JPA, Spring ORM, and Hibernate, providing a comprehensive integration for JPA repositories.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Database Driver

You also need the database driver for your specific database. For PostgreSQL, as mentioned in the example, the dependency would look like this:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>

Step 2: DataSource configuration

# DataSource configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/mydatabase
spring.datasource.username=myusername
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.postgresql.Driver

# Custom properties for demonstration
myapp.datasource.max-pool-size=30
myapp.datasource.min-idle=5

Step 3: Use @ConfigurationProperties or Environment to Inject Properties

There are multiple ways to inject these properties into your @Bean method. One common approach is to use @ConfigurationProperties to bind a configuration properties class to these properties. Another approach is to use the Environment abstraction or @Value annotations directly in your @Configuration class.

Using @ConfigurationProperties (Preferred for Type Safety and Grouping)

First, define a configuration properties class:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;

@ConstructorBinding
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
    private final String url;
    private final String username;
    private final String password;
    private final String driverClassName;

    // Constructor, Getters
}

Step 4: Define the DataSource Bean

Next, you create a configuration class where you define your DataSource bean:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfig {

    private final DataSourceProperties properties;

    public DataSourceConfig(DataSourceProperties properties) {
        this.properties = properties;
    }

    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        dataSource.setDriverClassName(properties.getDriverClassName());

        // Use additional custom properties as needed
        // Example: dataSource.setMaximumPoolSize(...);

        return dataSource;
    }
}

Explanation

  • @Configuration: This annotation marks the class as a source of bean definitions.
  • @Bean: This marks the dataSource method as a bean definition method. When the Spring context is loaded, it will execute this method and register the returned object (a DataSource in this case) in the application context.
  • Custom DataSource Configuration: The method dataSource creates a new DriverManagerDataSource, which is a simple implementation of the DataSource interface that is configured with the PostgreSQL database connection details. You can specify the driver class name, the database URL, username, and password.

Why Use @Bean Here?

Using @Bean allows for custom configuration of the DataSource beyond what’s provided by Spring Boot’s auto-configuration. This approach is particularly useful if you:

  • Need to connect to multiple data sources.
  • Require specific configurations for your database connections that aren’t directly supported by Spring Boot properties.
  • Want to programmatically configure how the DataSource is set up, perhaps based on dynamic conditions or external configuration sources.

This example showcases how @Bean can be used for explicit bean configuration, providing you with the flexibility to set up your Spring application components exactly as needed.

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over