Core Annotations & Auto-Configuration
Four annotations do almost identical things mechanically, and picking the wrong one is a code-smell, not a bug. This module is why they're different, and how Boot decides what to wire up without you asking.
Learning objectives
- Beginner: Use @Service, @Repository, and @RestController by their intended role consistently across a small project, even though they're all mechanically @Component.
- Intermediate: Recognize when auto-configuration has silently provided a bean you didn't define, by checking what starters are on the classpath rather than assuming "it just works."
- Advanced: Deliberately override one piece of Boot's auto-configuration (e.g. a custom DataSource) and understand exactly why your bean takes precedence, via @ConditionalOnMissingBean's semantics.
◆ The problem
Mechanically, @Component, @Service, @Repository, and @Controller all do the exact same thing — register the class as a bean. If that's true, why do four different annotations exist instead of one?
Each stereotype annotation is @Component underneath, but signals the class's architectural role to both human readers and Spring itself — and some carry extra behavior beyond plain registration.
| Annotation | Role | Extra behavior |
|---|---|---|
| @Component | Generic, unspecified role | None beyond bean registration. |
| @Service | Business logic layer | None beyond bean registration — purely a semantic signal for readability. |
| @Repository | Data access layer | Enables automatic translation of database-specific exceptions into Spring's unified DataAccessException hierarchy. |
| @Controller / @RestController | Web layer | Registers the class with the DispatcherServlet 's request mapping so its methods can handle HTTP requests (Module 06). |
▲ Pitfall
Using generic @Component everywhere "because it works" throws away real information — @Repository 's exception translation specifically is easy to lose without noticing, since the code still compiles and mostly works, it just leaks raw JDBC/Hibernate exceptions instead of Spring's consistent exception types.
@ComponentScan tells the container which packages to scan for stereotype-annotated classes. Spring Boot's @SpringBootApplication defaults this to the package containing your main class and everything beneath it — which is precisely why the conventional advice is "put your main class in the root package of your application": anything outside that subtree won't be found unless you configure @ComponentScan explicitly.
// Roughly equivalent to writing all three yourself: @Configuration @EnableAutoConfiguration @ComponentScan public class DemoApplication { }
| Component | Job |
|---|---|
| @Configuration | Marks this class as itself a source of bean definitions. |
| @EnableAutoConfiguration | Turns on Boot's auto-configuration mechanism (§04.4). |
| @ComponentScan | Scans for stereotype-annotated beans (§04.2). |
💻 Code example
// Roughly equivalent to writing all three yourself: @Configuration @EnableAutoConfiguration @ComponentScan public class DemoApplication { }
◆ Under the hood
Auto-configuration works through classes conditionally registered based on what's actually present — annotated with conditions like @ConditionalOnClass (only apply if a specific class is on the classpath) and @ConditionalOnMissingBean (only apply if you haven't already defined your own bean of that type). This is why adding spring-boot-starter-data-jpa (Module 05) alone gets you a working DataSource and EntityManager with zero manual configuration — Boot detected the JPA and JDBC driver classes on the classpath and auto-configured beans for them — but defining your own DataSource bean explicitly silently takes precedence over Boot's default, because of that @ConditionalOnMissingBean guard.
This conditional design is what makes auto-configuration additive rather than restrictive: it fills in sensible defaults only where you haven't already made a decision yourself.
✓ Quick recap
What extra behavior does @Repository add beyond plain bean registration? Automatic translation of database-specific exceptions into Spring's unified DataAccessException hierarchy. What three annotations does @SpringBootApplication combine? @Configuration, @EnableAutoConfiguration, and @ComponentScan. Why does defining your own DataSource bean override Boot's auto-configured one? Auto-configuration classes are commonly guarded by @ConditionalOnMissingBean, so they only apply when you haven't already provided your own.
Want a visual for this concept?
Generate a diagram tailored to “Core Annotations & Auto-Configuration” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →