Difference between Component Service Repository Controller
In Spring, Stereotype Annotations are specialized markers used to designate classes as Spring-managed Beans within specific architectural layers of an enterprise application.
🟢 Junior Level
In Spring, Stereotype Annotations are specialized markers used to designate classes as Spring-managed Beans within specific architectural layers of an enterprise application.
All specialized stereotype annotations inherit directly from the foundational @Component meta-annotation.
[@Component] (Root Meta-Annotation)
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
[@Service] [@Repository] [@Controller]
Business Layer Data Access (DAO) Spring MVC Views
│
▼
[@RestController]
REST APIs (JSON/XML)
Stereotypes Comparison Matrix
| Annotation | Architectural Layer | Semantic Purpose | Special Runtime Behavior |
|---|---|---|---|
@Component |
Generic / Any | General-purpose managed bean (utilities, helpers, clients) | None (standard bean lifecycle) |
@Service |
Service Layer | Business logic, calculations, domain orchestration | None (semantic marker for AOP pointcuts) |
@Repository |
Persistence (DAO) | Data access, database queries, and CRUD operations | Yes: Automatic Exception Translation to Spring’s DataAccessException |
@Controller |
Presentation | Web controllers returning rendered HTML templates | Yes: DispatcherServlet binding and template ViewResolver routing |
@RestController |
REST Web Services | HTTP API endpoints returning JSON/XML | Yes: Automatic Serialization via @ResponseBody and HttpMessageConverter |
🟡 Middle Level
Meta-Annotation Architecture
In the Spring Framework source code, @Service, @Repository, and @Controller are directly meta-annotated with @Component:
// Spring Framework Source Code:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // <-- Declares this annotation as an extension of @Component!
public @interface Service { ... }
Because of this meta-annotation hierarchy, Spring’s @ComponentScan scanner discovers all classes annotated with @Service, @Repository, or @Controller automatically, treating them as valid @Component beans.
@Controller vs @RestController
The distinction between @Controller and @RestController dictates how HTTP responses are processed:
@Controller(Traditional Server-Side MVC):- Returns a
Stringrepresenting a template view name. - Spring’s
ViewResolver(Thymeleaf, FreeMarker, JSP) locates the template on disk and renders HTML to the client:@Controller public class WebPageController { @GetMapping("/dashboard") public String showDashboard(Model model) { model.addAttribute("username", "Alex"); return "dashboard"; // Renders src/main/resources/templates/dashboard.html } }
- Returns a
@RestController(Headless RESTful APIs):- Composed of
@Controller+@ResponseBody. - The returned object is never passed to a
ViewResolver. Instead, it is serialized directly into the HTTP response body (defaulting to JSON via Jackson’sMappingJackson2HttpMessageConverter):@RestController // = @Controller + @ResponseBody on every method public class UserApiController { @GetMapping("/api/users/{id}") public UserDto getUser(@PathVariable Long id) { return new UserDto(id, "Alex"); // Serialized directly to: {"id": 1, "name": "Alex"} } }
- Composed of
🔴 Senior Level
The Key Functional Difference: Exception Translation in @Repository
Among all stereotype annotations, @Repository is the only annotation that introduces active runtime behavioral changes.
The Problem: Vendor Lock-In via Exceptions
Different database drivers and ORM frameworks throw distinct, vendor-specific low-level exceptions:
- JDBC throws checked
java.sql.SQLException. - Hibernate throws
org.hibernate.HibernateException. - JPA throws
jakarta.persistence.PersistenceException.
If the service layer caught these raw exceptions directly, business logic would be tightly coupled to a specific database implementation.
The PersistenceExceptionTranslationPostProcessor Engine:
- When Spring detects
@Repositoryon a bean, thePersistenceExceptionTranslationPostProcessor(aBeanPostProcessor) wraps the DAO bean in a dynamic AOP proxy. - The proxy applies a
PersistenceExceptionTranslationAdvisor. - When database calls fail, raw vendor exceptions are intercepted and converted into Spring’s unified, unchecked (
RuntimeException) hierarchy:DataAccessException.
Native Exception (java.sql.SQLException / HibernateException / PersistenceException)
│
▼ [Intercepted by PersistenceExceptionTranslator]
org.springframework.dao.DataAccessException
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
DuplicateKeyException DataIntegrityViolationException CannotAcquireLockException
(Unique constraint) (Foreign key / NOT NULL) (Database deadlocks)
[!WARNING] If you replace
@Repositorywith@Componentor@Serviceon a DAO class, the bean will still be registered and injected normally, but automatic exception translation will be completely disabled. Your service layer will be forced to catch raw vendor exceptions.
Layer-Targeted AspectJ Pointcuts
Using specific stereotype annotations enables clean, decoupled architecture rules via Aspect-Oriented Programming (AOP):
@Aspect
@Component
public class LayerMonitoringAspect {
// Matches all public methods in classes annotated with @Service:
@Around("@within(org.springframework.stereotype.Service)")
public Object profileServices(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
// Matches all database calls in classes annotated with @Repository:
@Around("@within(org.springframework.stereotype.Repository)")
public Object profileDatabaseAccess(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
}
4 Tricky Questions
1. Which stereotype annotation introduces actual runtime functional behavior rather than just semantic metadata?
Answer:
@Repository.
While @Service and @Component serve exclusively as semantic markers and component scanning targets, @Repository activates the PersistenceExceptionTranslationPostProcessor.
This BeanPostProcessor automatically wraps the repository bean in a dynamic AOP proxy that intercepts raw, low-level database exceptions (such as JDBC’s SQLException or Hibernate’s HibernateException) and translates them into Spring’s database-agnostic, unchecked DataAccessException hierarchy.
2. What happens if a developer replaces @Service with @Component on a business logic class?
Answer:
From a basic dependency injection and bean lifecycle perspective, nothing changes: Spring will still discover the class via @ComponentScan, register it in the ApplicationContext, and inject it into callers.
However, replacing @Service with @Component:
- Degrades code readability and architectural maintainability by failing to indicate domain layer boundaries.
- Disables AOP pointcut rules that target the service layer specifically (e.g.
@within(org.springframework.stereotype.Service)). - Breaks architectural enforcement tools (such as ArchUnit) that validate dependency directions between presentation, service, and persistence layers.
3. What is the fundamental architectural difference between @Controller and @RestController?
Answer:
@Controlleris intended for server-side template rendering in Spring MVC. The return value of a controller method is treated as a logical view name, which is forwarded to a configuredViewResolver(e.g. Thymeleaf, JSP) to render an HTML response.@RestControlleris a convenience composite annotation consisting of@Controller+@ResponseBody. It instructs Spring’sRequestResponseBodyMethodProcessorto bypass theViewResolverentirely. The returned domain object is serialized directly into the HTTP response body using an appropriateHttpMessageConverter(defaulting to Jackson for JSON).
4. Why did Spring design the DataAccessException hierarchy to be unchecked (RuntimeException) instead of checked?
Answer:
Checked exceptions (like JDBC’s SQLException) force developers to clutter business methods with mandatory try-catch blocks or throws clauses, even though the vast majority of database errors (deadlocks, constraint violations, lost connections) are fatal and unrecoverable at the call site.
By making DataAccessException unchecked (extending RuntimeException), Spring adheres to modern exception handling principles:
- Business logic remains clean and decoupled from low-level infrastructure failures.
- Unrecoverable database exceptions bubble up automatically to centralized global handlers (such as
@ControllerAdviceor transaction managers) for consistent error logging and HTTP 500 mapping.
🎯 Interview Cheat Sheet
30-Second Elevator Pitch
Spring provides four primary stereotype annotations that inherit from
@Component:
@Component: General-purpose managed bean.@Service: Semantic marker for domain business logic (useful for transaction anchors and AOP pointcuts).@Repository: Persistence layer component. Introduces active runtime behavior: wraps the DAO in an AOP proxy viaPersistenceExceptionTranslationPostProcessorto convert vendor SQL/Hibernate exceptions into Spring’s uncheckedDataAccessExceptionhierarchy.@Controller: Spring MVC controller returning HTML view names.@RestController: Composite@Controller+@ResponseBodyreturning JSON/XML directly to HTTP clients.
Stereotype Hierarchy & Capabilities
| Stereotype | Extends @Component? |
Special Runtime Proxy Applied? | Intended Output |
|---|---|---|---|
@Component |
Root | No | Generic Bean |
@Service |
Yes | No | Business Result |
@Repository |
Yes | Yes (Exception Translation) | Database Entities / DTOs |
@Controller |
Yes | Yes (DispatcherServlet View Binding) | HTML View Name |
@RestController |
Yes | Yes (HttpMessageConverter Serialization) | JSON / XML Payload |
Red Flags (DO NOT Say)
- ❌ “The
@Serviceannotation automatically makes every method transactional.” (Transactions require explicit@Transactionalannotations). - ❌ “All four stereotypes are 100% functionally identical under the hood.” (
@Repositoryactivates dynamic exception translation). - ❌ “@RestController cannot return custom HTTP status codes.” (Status codes are fully customizable via
ResponseEntity<T>or@ResponseStatus). - ❌ “You must only use
@Componentbecause other stereotypes are deprecated.” (Using specific stereotypes is a mandatory architectural standard in Spring).