@ComponentScan & Stereotypes
Beginner@ComponentScan instructs Spring to detect @Component, @Service, @Repository, and @Controller classes and register them as beans automatically.
Overview
@ComponentScan tells Spring which packages to scan for classes annotated with stereotype annotations. The four core stereotypes are: @Component (generic), @Service (business logic layer), @Repository (data access layer, adds exception translation), and @Controller/@RestController (web layer). @SpringBootApplication includes @ComponentScan pointed at the main class's package, so everything in the same package tree is auto-discovered. You can restrict or expand the scan with basePackages, includeFilters, and excludeFilters.
Stereotype Annotations
@Service, @Repository, and @Controller are all meta-annotated with @Component — they are specialisations that carry semantic meaning and enable targeted AOP or exception translation.
// @Component — generic bean; no additional semantics
@Component
public class PasswordEncoder { ... }
// @Service — marks business logic / service layer
// No technical difference from @Component, but signals intent
@Service
public class OrderService {
public Order placeOrder(PlaceOrderRequest req) { ... }
}
// @Repository — data access layer
// Spring wraps methods to translate JDBC/JPA exceptions to DataAccessException
@Repository
public class JdbcOrderRepository {
public Optional<Order> findById(Long id) { ... }
// SQLException thrown here → auto-translated to DataAccessException
}
// @Controller — web layer (Spring MVC)
@Controller
public class OrderViewController { ... }
// @RestController — web layer for REST APIs (@Controller + @ResponseBody)
@RestController
public class OrderApiController { ... }Customising @ComponentScan
By default, @SpringBootApplication scans the package of the main class. Use basePackages to scan additional packages, or includeFilters/excludeFilters to fine-tune what gets picked up.
// Explicit base packages (multi-module project)
@SpringBootApplication
@ComponentScan(basePackages = {
"com.example.orders",
"com.example.shared",
"com.example.infrastructure"
})
public class OrderServiceApp { ... }
// Exclude specific classes or packages
@ComponentScan(
basePackages = "com.example",
excludeFilters = @ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "com\.example\.legacy\..*"
)
)
// Include only classes annotated with a custom annotation
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {}
@ComponentScan(
basePackages = "com.example",
includeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION, classes = EventHandler.class
),
useDefaultFilters = false // only scan for @EventHandler
)Bean Naming & Conflict Resolution
Bean name defaults to the simple class name with a lowercase first letter. Override with @Component("customName"). Conflicts occur when two beans have the same name — the last definition wins in @ComponentScan (or throws a conflict exception in strict mode).
// Default name: "orderService"
@Service
public class OrderService { ... }
// Custom name: "legacyOrderService"
@Service("legacyOrderService")
public class LegacyOrderService { ... }
// Inject by name when multiple beans of the same type exist
@Service
public class OrderFacade {
private final OrderService orderService; // primary
private final OrderService legacyOrderService; // secondary
public OrderFacade(
@Qualifier("orderService") OrderService orderService,
@Qualifier("legacyOrderService") OrderService legacyOrderService) {
this.orderService = orderService;
this.legacyOrderService = legacyOrderService;
}
}
// Or mark one as @Primary for default injection
@Service
@Primary
public class OrderService { ... }Key Points to Remember
- 1@SpringBootApplication includes @ComponentScan rooted at the main class's package.
- 2@Service, @Repository, @Controller are semantic aliases for @Component.
- 3@Repository adds PersistenceExceptionTranslationPostProcessor — translates DB exceptions.
- 4basePackages restricts scanning; includeFilters/excludeFilters fine-tune discovery.
- 5Default bean name = simple class name with lowercase first letter.
- 6Use @Qualifier to disambiguate when multiple beans of the same type exist.
Interview Questions
Sign in to ask AriaWhat is the difference between @Component, @Service, and @Repository?
What does @Repository add beyond @Component?
How does @SpringBootApplication enable component scanning?
How would you exclude a package from component scanning?
What happens when two beans of the same type are found during autowiring?
Ask Aria about @ComponentScan & Stereotypes
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.