@Bean, @Component, @Service, @Repository Explained

2 minute read

Spring provides multiple ways to register beans. This chapter clarifies when to use @Component, @Service, @Repository, @Controller, @Configuration, and @Bean.


Stereotype Annotations

@Component                 ← Generic Spring-managed bean
    ├── @Service           ← Business logic
    ├── @Repository        ← Data access (adds exception translation)
    └── @Controller        ← Web controller
        └── @RestController ← REST API controller (@Controller + @ResponseBody)

All are specializations of @Component — Spring discovers and manages them all the same way. The difference is semantic (communicates intent) and sometimes functional.


@Component — Generic Bean

@Component
public class EmailValidator {
    public boolean isValid(String email) {
        return email != null && email.contains("@");
    }
}

Use @Component when the class doesn’t fit @Service, @Repository, or @Controller.


@Service — Business Logic

@Service
public class BookService {

    private final BookRepository bookRepository;

    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public Book createBook(String title, String author) {
        // Business rules here
        if (title == null || title.isBlank()) {
            throw new IllegalArgumentException("Title cannot be blank");
        }
        Book book = new Book(title, author);
        return bookRepository.save(book);
    }
}

@Repository — Data Access

@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
    List<Book> findByAuthor(String author);
    Optional<Book> findByIsbn(String isbn);
}

@Repository adds exception translation — converts database-specific exceptions (like SQLIntegrityConstraintViolationException) into Spring’s DataAccessException hierarchy.

For Spring Data JPA interfaces, @Repository is optional — Spring Data adds it automatically.


@Controller and @RestController

// For server-side rendered pages (Thymeleaf, etc.)
@Controller
public class HomeController {
    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("title", "Welcome");
        return "home";  // returns view name
    }
}

// For REST APIs (returns JSON directly)
@RestController
@RequestMapping("/api/books")
public class BookController {
    @GetMapping
    public List<Book> getAll() {
        return bookService.findAll();  // returns JSON
    }
}

@RestController = @Controller + @ResponseBody (every method returns JSON/data, not a view).


@Configuration and @Bean

Use @Bean when you need to register third-party classes that you can’t annotate:

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();  // third-party class
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

@Component vs @Bean

  @Component @Bean
Where On a class On a method inside @Configuration
Use for Your own classes Third-party classes
Auto-detected Yes (component scan) Yes (inside @Configuration)
Customization Limited Full control (constructor args, init)

When to Use What

Annotation Use For
@Service Business logic classes
@Repository Data access classes / interfaces
@RestController REST API endpoints
@Controller Server-side page rendering
@Component Utility classes, validators, anything else
@Configuration + @Bean Third-party libraries, complex bean creation

Component Scanning Rules

// Only scans com.bookstore and sub-packages
@SpringBootApplication  // in com.bookstore package
public class BookstoreApiApplication { }

// ✅ Found
com.bookstore.service.BookService
com.bookstore.controller.BookController

// ❌ NOT found
com.other.SomeUtility

Common Mistakes

Mistake Fix
Using @Component for everything Use the specific stereotype (@Service, @Repository)
Using @Bean for your own classes Use @Service / @Component — they’re simpler
Missing @Configuration on class with @Bean @Bean methods must be in @Configuration class
Annotating an interface with @Service Annotate the implementation, not the interface

Key Takeaways

  1. @Service, @Repository, @Controller are specializations of @Component.
  2. Use the most specific annotation — it documents intent.
  3. @Bean is for third-party classes you can’t annotate yourself.
  4. @Repository adds database exception translation.
  5. @RestController = @Controller + @ResponseBody.

What’s Next?

Next: application.properties and application.yml — configuring your Spring Boot application.

Updated: