Question

Spring @Component vs @Repository vs @Service: What's the Difference?

javaspringspring-mvcannotationsinversion-of-control

Question

In Spring, can @Component, @Repository, and @Service be used interchangeably, or do they provide specific functionality beyond simply marking a class?

For example, if a service class is annotated with @Service and I change it to @Component, will it still behave the same way?

Does the chosen annotation affect the behavior and functionality of the class, or is it mainly used for organization and readability?

Short Answer

By the end of this page, you will understand how Spring stereotype annotations work, what @Component, @Service, and @Repository have in common, and where they differ. You will also learn when they are interchangeable, when they are not, and why using the most specific annotation improves code clarity and framework integration.

Concept

Spring uses stereotype annotations to mark classes as beans that should be detected during component scanning and managed by the Spring container.

The three annotations in this question are closely related:

@Component
@Service
@Repository

The core idea

@Service and @Repository are specialized forms of @Component.

That means:

  • A class annotated with any of them can usually be discovered by component scanning.
  • Spring can create an object for that class and manage its lifecycle as a bean.
  • You can inject that bean into other classes using dependency injection.

What they have in common

All three typically:

  • Register the class as a Spring bean
  • Allow dependency injection
  • Participate in component scanning
  • Represent application-layer classes managed by Spring

What makes them different

The difference is mostly about meaning and framework behavior.

@Component

This is the most general stereotype. It says:

  • "This class is a Spring-managed component."

Use it when the class does not clearly belong to a more specific role.

@Service

This is a semantic specialization of @Component. It says:

  • "This class contains business logic."

In many Spring applications, @Service behaves the same as @Component at runtime. The main benefit is clearer design and better communication to other developers.

@Repository

This is also a specialization of @Component, but it has an important extra purpose:

  • "This class handles database access or persistence."

@Repository can trigger exception translation in Spring. That means low-level persistence exceptions may be converted into Spring's consistent DataAccessException hierarchy.

This is the main practical behavior difference among these annotations.

Why this matters

In real projects, these annotations help define architecture clearly:

  • @Controller or @RestController for web layer
  • @Service for business layer
  • @Repository for data access layer
  • @Component for general-purpose helper classes

Even when @Service and @Component behave similarly today, using the specific annotation makes your codebase easier to understand, maintain, and extend.

Mental Model

Think of @Component as a general label that says, "Put this object on Spring's staff list."

Then think of @Service and @Repository as job titles:

  • @Component = employee
  • @Service = business manager
  • @Repository = database specialist

All of them are employees, so they can enter the building and do work. But the job title tells everyone what role they play.

In one case, the job title can also change behavior:

  • @Repository not only says "database specialist"
  • it also allows Spring to treat certain database errors in a special way

So the labels are not only decorative. They are partly descriptive, and in some cases, they affect framework behavior too.

Take Quiz

Syntax and Examples

Basic syntax

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.stereotype.Repository;

@Component
public class EmailFormatter {
}

@Service
public class OrderService {
}

@Repository
public class OrderRepository {
}

Each of these classes can be discovered by component scanning and registered as a Spring bean.

Example with dependency injection

import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Repository
public class UserRepository {
    public String findUsernameById(long id) {
        return "alice";
    }
}

@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getDisplayName(long id) {
        return userRepository.findUsernameById(id).toUpperCase();
    }
}

What this shows

  • UserRepository is a Spring bean because it is marked with @Repository
  • UserService is a Spring bean because it is marked with @Service
  • Spring injects UserRepository into UserService
  • The service layer uses the repository layer to fetch data and apply business logic

If @Service becomes @Component

import org.springframework.stereotype.Component;

@Component
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getDisplayName(long id) {
        return userRepository.findUsernameById(id).toUpperCase();
    }
}

This will usually still work the same way as long as component scanning includes the class.

The main change is that the class no longer explicitly communicates that it belongs to the service layer.

Important exception: @Repository

Changing a repository class from @Repository to @Component may remove repository-specific behavior such as persistence exception translation in some setups.

So:

  • @Service ↔ @Component: often functionally similar
  • @Repository ↔ @Component: not always equivalent

Step by Step Execution

Consider this example:

@Repository
public class ProductRepository {
    public String findById(int id) {
        return "Laptop";
    }
}

@Service
public class ProductService {
    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    public String getProductLabel(int id) {
        String product = productRepository.findById(id);
        return "Product: " + product;
    }
}

Step by step

1. Spring scans the package

Spring looks for classes annotated with stereotypes such as:

  • @Component
  • @Service
  • @Repository

It finds both ProductRepository and ProductService.

2. Spring creates beans

Spring creates managed objects for both classes and stores them in the application context.

3. Spring resolves dependencies

ProductService needs a ProductRepository in its constructor.

Spring sees that a ProductRepository bean exists, so it injects it automatically.

4. Your code calls the service

If some controller or other bean calls:

productService.getProductLabel(10);

then this method runs.

5. The service calls the repository

Inside getProductLabel, this line runs:

String product = productRepository.findById(id);

The repository returns:

"Laptop"

6. The service adds business logic

The service returns:

"Product: Laptop"

What if @Service becomes @Component?

Spring would still:

  • detect the class
  • create the bean
  • inject the dependency

So execution would usually be unchanged.

What if @Repository becomes @Component?

The bean would still likely be created and injected, but you may lose repository-specific exception handling behavior. That is why repository classes should normally use @Repository.

Real World Use Cases

Where @Component is used

Use @Component for general-purpose classes that do not clearly belong to the service or persistence layer.

Examples:

  • utility classes managed by Spring
  • custom validators
  • token generators
  • file parsers
  • scheduled task helpers
@Component
public class SlugGenerator {
    public String toSlug(String text) {
        return text.toLowerCase().replace(" ", "-");
    }
}

Where @Service is used

Use @Service for business rules and application workflows.

Examples:

  • order processing
  • payment logic
  • account registration rules
  • email sending coordination
  • report generation
@Service
public class PaymentService {
    public boolean processPayment(double amount) {
        return amount > 0;
    }
}

Where @Repository is used

Use @Repository for database access.

Examples:

  • JPA or JDBC data access classes
  • custom query classes
  • persistence adapters
  • DAO-style classes
@Repository
public class CustomerRepository {
    public void save(Customer customer) {
        // database logic
    }
}

In layered applications

A common flow looks like this:

  • controller receives request
  • service applies business rules
  • repository reads or writes data

This separation makes applications easier to test and maintain.

Take Quiz

Real Codebase Usage

In real projects, developers rarely choose these annotations randomly. They use them to communicate architecture and to support framework conventions.

Common pattern: layered architecture

@RestController
public class OrderController {
    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
}

@Service
public class OrderService {
    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

@Repository
public class OrderRepository {
}

This tells readers immediately what each class is responsible for.

Guard clauses and validation in services

Services often contain checks before calling repositories:

@Service
public class AccountService {
    public void register(String email) {
        if (email == null || email.isBlank()) {
            throw new IllegalArgumentException("Email is required");
        }

        // business logic continues
    }
}

Error handling in repositories

Repositories isolate persistence logic so database-related failures stay in one place.

@Repository
public class JdbcInventoryRepository {
    public int countItems() {
        // query database
        return 0;
    }
}

Why teams prefer specific stereotypes

Using the most specific stereotype helps with:

  • code readability
  • architecture reviews
  • onboarding new developers
  • consistent package structure
  • framework integrations such as exception translation

Practical guideline

  • Use @Repository for persistence classes
  • Use @Service for business logic classes
  • Use @Component for everything else that should be a Spring bean

Common Mistakes

1. Using @Component everywhere

This works technically in many cases, but it hides the role of each class.

Less clear

@Component
public class InvoiceService {
}

@Component
public class InvoiceRepository {
}

Better

@Service
public class InvoiceService {
}

@Repository
public class InvoiceRepository {
}

2. Thinking @Service adds major built-in business logic features

Beginners sometimes assume @Service automatically changes how methods run.

Usually, it does not add special runtime behavior by itself. It mainly provides semantic meaning as a specialized @Component.

3. Replacing @Repository with @Component for database classes

This can be a real mistake because repository-specific exception translation may no longer apply.

Risky

@Component
public class UserRepository {
    // database code
}

Better

@Repository
public class UserRepository {
    // database code
}

4. Confusing stereotypes with bean scope

These annotations do not decide whether a bean is singleton, prototype, request-scoped, or session-scoped.

Bean scope is controlled separately, for example with @Scope.

5. Forgetting component scanning

Even if a class has @Service or @Repository, Spring must still scan the package.

If the package is outside the scan path, the bean will not be created.

6. Putting business logic in repositories

Repositories should focus on persistence. Services should contain business rules.

Not ideal

@Repository
public class DiscountRepository {
    public double calculateDiscount(Customer customer) {
        return 0.15;
    }
}

Better

@Service
public class DiscountService {
    public double calculateDiscount(Customer customer) {
        return 0.15;
    }
}

Comparisons

Quick comparison

AnnotationIs it a Spring bean stereotype?Main purposeExtra behaviorBest use
@ComponentYesGeneral-purpose Spring-managed classUsually none specificHelpers, utilities, generic components
@ServiceYesBusiness logic layerMostly semantic in common usageServices, workflows, application rules
@RepositoryYesPersistence/data access layerException translation for persistence errorsDAO, JPA, JDBC, database access

@Service vs @Component

Point@Service@Component
MeaningBusiness logicGeneral bean
Bean registrationYesYes
Common runtime differenceUsually noneUsually none
Best choice for service classesYesPossible, but less clear

@Repository vs @Component

Point@Repository@Component
MeaningData accessGeneral bean
Bean registrationYesYes
Exception translationOften yesUsually no
Best choice for DB classesYesUsually no

Are they interchangeable?

  • @Service and @Component are often interchangeable in behavior, but not equally expressive.
  • @Repository and @Component are not always interchangeable because @Repository may enable extra persistence-related behavior.
Take Quiz

Cheat Sheet

Quick rules

  • @Component = general Spring-managed bean
  • @Service = business logic bean
  • @Repository = data access bean
  • @Service and @Repository are specialized versions of @Component

What all three do

  • make the class eligible for component scanning
  • register it as a Spring bean
  • allow dependency injection

Important difference

  • @Repository can enable persistence exception translation
  • @Service is usually mainly semantic and architectural

Good defaults

@Component   // generic helper or utility
@Service     // business logic
@Repository  // database access

Typical layered structure

@RestController
class UserController {}

@Service
class UserService {}

@Repository
class UserRepository {}

Common interview-style answer

@Service and @Repository are stereotype annotations built on top of @Component. All can create Spring beans, but @Repository may add exception translation, while @Service mainly adds semantic meaning.

Edge case to remember

If you change a class from @Service to @Component, it will usually still work. If you change a class from @Repository to @Component, it may still work as a bean, but some repository-specific behavior may be lost.

FAQ

Can @Component, @Service, and @Repository all create Spring beans?

Yes. All three can mark a class for component scanning so Spring can create and manage it as a bean.

Is @Service just a special kind of @Component?

Yes. @Service is a specialization of @Component, mainly used to indicate business logic.

Does changing @Service to @Component usually break anything?

Usually no, as long as component scanning still finds the class. The bean will typically behave the same way.

Why should I use @Repository instead of @Component for database classes?

Because @Repository clearly marks persistence code and can enable Spring's persistence exception translation.

Does @Service provide extra runtime features by default?

In common usage, not much. Its biggest value is semantic clarity and better architecture communication.

Are these annotations required for dependency injection?

A class usually needs to be registered as a bean somehow. These annotations are one common way to do that through component scanning.

What happens if Spring does not scan the package?

The class will not be registered as a bean, even if it has @Component, @Service, or @Repository.

Should I always use the most specific stereotype?

Yes, in most cases. It makes the code easier to understand and can enable framework-specific behavior where relevant.

Take Quiz

Mini Project

Description

Build a small layered Spring example with a utility component, a service, and a repository. This project helps you see where each stereotype belongs and how the classes work together in a realistic structure.

Goal

Create a simple user lookup flow where a service calls a repository and also uses a general-purpose component.

Requirements

  • Create one class annotated with @Component for formatting usernames
  • Create one class annotated with @Repository that returns a hardcoded username
  • Create one class annotated with @Service that uses both classes
  • Add one runner or test method that calls the service and prints the result
Take Quiz

Keep learning

Related questions

View more