@Bean, @Component, @Service, @Repository Explained
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,
@Repositoryis 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
@Service,@Repository,@Controllerare specializations of@Component.- Use the most specific annotation — it documents intent.
@Beanis for third-party classes you can’t annotate yourself.@Repositoryadds database exception translation.@RestController=@Controller+@ResponseBody.
What’s Next?
Next: application.properties and application.yml — configuring your Spring Boot application.