Annotations are often a stumbling block for anyone learning Spring Boot.
In this article, we take a close look at one of the most important and most confusing of them for beginners: @Component. We also explain how it differs from the similar-looking @Bean, and when to use each.

What Is @Component?

What the Spring Component annotation is (clearing up the terminology)

When you search, you will see several variations such as “Spring Component,” “@Component annotation,” and “component annotation,” but they all refer to the same thing.
It is the org.springframework.stereotype.Component annotation provided by the Spring Framework. When you add it to a class, the Spring container automatically detects and manages that class as a Bean. In Spring Boot, component scanning is enabled by default, so the basic behavior is that simply adding @Component registers the class with the DI container.

A similar term is “Spring Bean,” which refers to any instance registered with the Spring container. A class annotated with @Component is one kind of Bean, and Beans also include those defined via @Bean methods or registered through XML configuration.

@Component is an annotation for registering a class with the Spring container as a Bean. Put simply, it is a marker that tells Spring, “Please manage this class!”
Spring automatically instantiates any class annotated with @Component and makes it available whenever it is needed.

For example, suppose you have a simple class like the following.

@Component
public class MyService {

    public String getMessage() {
        return "Hello from MyService!";
    }
}

Because this MyService class carries the @Component annotation, an instance of MyService is created automatically when the Spring Boot application starts, and it is managed by the Spring container.
Once it is under the Spring container’s management, other classes can easily inject this MyService using the @Autowired annotation.

@Service
public class MyController {

    @Autowired
    private MyService myService;

    public String displayMessage() {
        return myService.getMessage();
    }
}

In this way, using @Component lets you delegate instance creation and management to Spring, which keeps your code simpler and improves maintainability.

What Is @Bean?

Next, let’s look at @Bean. Like @Component, @Bean registers a Bean with the Spring container, but it differs from @Component in an important way.
Whereas @Component is applied to an entire class, @Bean is applied to a method. The return value of that method is then registered as a Bean.

For example, you can define a Bean called MyBean using the @Bean annotation as shown below. Note that @Bean methods must be defined inside a class annotated with @Configuration.

@Configuration
public class MyConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

class MyBean {
    // ...
}

In this case, the myBean() method of the MyConfig class is executed, and its return value, an instance of MyBean, is registered with the Spring container.

When to Use @Component vs. @Bean

Differences in scope and lifecycle

Both @Component and @Bean default to singleton scope, meaning only one instance is created in the container. You can change this behavior to create a new instance per request by adding something like @Scope("prototype"), but the difference is that @Component applies it to a class while @Bean applies it to a method.

Lifecycle hooks (@PostConstruct / @PreDestroy) work with both, but @Bean has the advantage of letting you specify methods from external libraries via the initMethod / destroyMethod attributes. If you need to hook into the initialization of an external class that you cannot annotate yourself, @Bean is the better fit.

Compatibility with conditional Bean registration (@ConditionalOnMissingBean)

In Spring Boot’s auto-configuration, a very common pattern combines @Bean methods with @ConditionalOnMissingBean to “provide a default unless the user has defined their own Bean.” This kind of conditional registration is hard to express with @Component alone, so the standard practice for library authors providing default Beans is to write them with @Configuration + @Bean.

For a more detailed look at how to use @Configuration / @Bean, see the related article What Are @Configuration / @Bean in Spring Boot?.

So, which should you use: @Component or @Bean?
As a general rule, use @Component when you simply want Spring to manage a class, and use @Bean when a Bean requires complex initialization logic or when you need to manage multiple Beans of the same class.

With @Component, Spring Boot resolves dependencies for you nicely, so it is well suited to simple service classes that do not need complex initialization.

@Bean, on the other hand, allows more flexible Bean definitions, making it a good choice for Beans that require complex initialization or for defining Beans from external libraries where you did not write the class yourself. For example, if you need a Bean with initialization logic such as a database connection, or you want to define multiple Beans of the same class for different purposes, @Bean offers greater flexibility and is the more appropriate choice.

A Decision Table for When You’re Unsure

To speed up decisions in real-world work, here is a table summarizing common cases.

CaseRecommended approachReason
Register your own Service/Repository class@Component (or @Service/@Repository)Can be registered automatically via component scanning
Turn an external library class into a Bean@BeanYou cannot annotate the class
Initialization requires conditional logic or parameter calculation@BeanYou can write flexible creation logic inside the method
Register multiple Beans of the same type and choose between them@Bean + @QualifierEasy to control explicitly by Bean name

@Service and @Repository are internally part of the @Component family (stereotypes).
Functionally they all register Beans, but because they make the intent explicit in code, they are commonly used as follows:

  • @Service: business logic layer
  • @Repository: persistence layer (benefits from exception translation)
  • @Controller / @RestController: web layer

Using @Component for everything will work, but separating them into role-specific annotations improves maintainability.

Common Pitfalls

1. Placing a class outside the ComponentScan range

If a class annotated with @Component is not recognized as a Bean, this is almost always the cause.
The package containing the main class annotated with @SpringBootApplication, along with its subpackages, is scanned automatically, so classes in packages above it are not detected. Review the location of your main class and your package structure.

2. Multiple Beans of the same type causing ambiguous injection

In this case, specify the injection target explicitly with @Primary or @Qualifier.
If you specify nothing, a NoUniqueBeanDefinitionException is thrown.

3. Overusing field injection and making tests harder

Field injection with @Autowired is convenient, but it tends to make swapping dependencies in tests difficult.
In real-world projects, we recommend constructor injection as the default.

Make Constructor Injection the Default in Production Code

Receiving dependencies through the constructor, as shown below, makes the dependencies explicit and the class easier to test.

@Service
public class OrderService {
    private final PaymentClient paymentClient;

    public OrderService(PaymentClient paymentClient) {
        this.paymentClient = paymentClient;
    }
}

Because required dependencies are made explicit in the constructor, it is also easier to prevent missed initialization.

@Primary/@Qualifier for Handling Multiple Implementations

When there are multiple implementations of the same interface, be explicit about your injection strategy.

public interface Notifier {
    void send(String message);
}

@Component
@Primary
public class EmailNotifier implements Notifier {
    public void send(String message) {}
}

@Component
public class SlackNotifier implements Notifier {
    public void send(String message) {}
}

Where you want to use a specific implementation, specifying @Qualifier("slackNotifier") prevents the wrong Bean from being injected.

Design Rules for Separating Responsibilities

  • Split packages by domain and keep the scan range clear
  • Follow the one-class-one-responsibility rule and avoid giant Service classes
  • Avoid overusing @Component and use meaningful stereotypes instead

Following these rules consistently keeps the project structure easy to follow even as Bean definitions grow.

Summary

@Component makes it easy to create Beans that Spring manages automatically, while @Bean enables more flexible Bean definitions.
In other words, @Component can be thought of as a simplified form of the initialization that @Bean performs.

By understanding the characteristics of each and using them appropriately, you can build more efficient and maintainable Spring Boot applications.
When you are unsure which to use, keep the differences above in mind and choose the annotation that fits your requirements!