Stereotype Annotations
Spring lets you tell the container "this class is a bean" by tagging it with an annotation, instead of declaring it in a config class.
Introduction
Spring lets you tell the container "this class is a bean" by tagging it with an annotation, instead of declaring it in a config class. These tags are called stereotypes, and they also document the role each class plays in your architecture.
A reader of your code should be able to scan a package and instantly know which classes are services, which are persistence, and which are HTTP entry points — without reading their bodies.
Understanding the topic
The four core stereotypes:
@Component— generic bean; use when no other tag fits.@Service— business logic; communicates intent to readers.@Repository— data access; also translates JDBC/JPA exceptions to Spring'sDataAccessExceptionhierarchy.@Controller/@RestController— web entry points; participate in MVC argument resolution and response writing.
All four are meta-annotated with @Component, so component scanning picks them up the same way. The difference is semantic — plus a few framework hooks (like exception translation for repositories).
Syntax reference
Component scanning picks these up automatically:
@Configuration@ComponentScan("com.acme.shop")public class AppConfig {}@Servicepublic class CartService { /* discovered by scan */ }@Repositorypublic class JdbcCartRepository implements CartRepository { /* discovered by scan */ }@RestController@RequestMapping("/api/cart")public class CartController { /* discovered by scan */ }
Informative example
Defining a custom stereotype: you can build your own annotations on top of the standard ones to encode project conventions.
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Service@Transactional(readOnly = true)public @interface ReadOnlyService {}@ReadOnlyServicepublic class PricingQueryService { /* automatically a read-only @Service */ }
Real-world use
Large codebases often have 5–10 custom stereotypes encoding rules like "all controllers must have CORS enabled" or "all repositories must use the analytics datasource". Used sparingly, this is a powerful way to keep architecture consistent.
Best practices
- Use the most specific stereotype — future developers (including you) will thank you.
- Keep packages narrow; broad scans slow startup and pick up classes you didn't mean to register.
- Never put two stereotypes on the same class — pick one role per class.
Common mistakes
- Putting
@Componenton a class outside the scan base package — it silently becomes invisible. - Annotating an interface with a stereotype — Spring needs an implementation, not a contract.
Hands-on exercise
Try this: build a tiny shopping app with one controller, one service and one repository — each marked with the correct stereotype. Then deliberately move the controller out of the scanned package and confirm Spring no longer finds it. Move it back, and add a custom @AdminService stereotype that combines @Service with a security annotation.