What Does the @ComponentScan Annotation Do?
4. excludeFilters -> for tests 5. useDefaultFilters = false -> custom annotations 6. ASM -> does not load classes, reads bytecode
Junior Level
@ComponentScan tells Spring which packages to search for beans (@Component, @Service, @Repository).
@SpringBootApplication // Already includes @ComponentScan
public class Application { }
// Manual configuration:
@ComponentScan(basePackages = "com.example.services")
Rule:
- @SpringBootApplication scans the current package and all sub-packages
- Usually no need to configure manually
Middle Level
How Scanning Works
ClassPathBeanDefinitionScanner:
1. Reads .class files via ASM (library for reading bytecode without loading classes into JVM)
// This is important: classes do not go through full JVM initialization, their static blocks are not executed.
// Spring only reads annotations from .class files.
2. Searches for @Component, @Service... annotations
3. Creates BeanDefinition
4. Does NOT load classes into JVM!
Configuration
// Scan specific packages
@ComponentScan(basePackages = {"com.example.a", "com.example.b"})
// Type-safe (recommended!)
@ComponentScan(basePackageClasses = MyMarkerInterface.class)
// Exclude classes
@ComponentScan(excludeFilters = @Filter(Type.ASSIGNABLE_TYPE, classes = Config.class))
spring-context-indexer
For large projects -> slow scanning
Dependency: spring-context-indexer
-> Creates META-INF/spring.components at compile time
-> Spring reads list instead of scanning
-> Startup 2-3 times faster!
Senior Level
ConfigurationClassPostProcessor
Launches scanning:
1. Parses @Configuration classes
2. Processes @Import
3. Launches ClassPathBeanDefinitionScanner
4. Registers BeanDefinition
Filtering
@ComponentScan(
useDefaultFilters = false, // Disable @Component
includeFilters = @Filter(MyCustomAnnotation.class)
)
// This is useful if you want to scan only your custom annotations
// and ignore standard @Component/@Service. All standard beans
// will NOT be registered!
Production Experience
Real scenario: 10 seconds on scanning
5000 classes -> ASM scanning -> 10 seconds
Solution: spring-context-indexer
Result: 2 seconds
Best Practices
- basePackageClasses -> type-safe
- spring-context-indexer -> for large projects
- Limit packages -> do not scan unnecessary
- excludeFilters -> for tests
- useDefaultFilters = false -> custom annotations
- ASM -> does not load classes, reads bytecode
Summary for Senior
- @ComponentScan -> search for beans in packages
- ASM -> bytecode reading, not reflection
- ConfigurationClassPostProcessor -> launches scanning
- spring-context-indexer -> startup speedup
- basePackageClasses -> type-safe
- Filters -> include/exclude
Interview Cheat Sheet
Must know:
- @ComponentScan searches for @Component, @Service, @Repository, @Controller in specified packages
- @SpringBootApplication already includes @ComponentScan of current package and sub-packages
- ASM reads bytecode of .class files - classes are NOT loaded into JVM, static blocks are NOT executed
- ConfigurationClassPostProcessor launches scanning at an early phase
- spring-context-indexer creates META-INF/spring.components at compile time - startup 2-3 times faster
- basePackageClasses - type-safe alternative to string packages
- includeFilters / excludeFilters - fine-grained scanning control
Common follow-up questions:
- Why doesn’t Spring load classes during scanning? - ASM reads only annotations from bytecode, this is faster and safer (static blocks are not executed).
- How to speed up scanning in a large project? - spring-context-indexer: meta-file created at compile time, Spring reads it instead of walking classpath.
- What happens with excludeFilters = @Filter(Type.ASSIGNABLE_TYPE, classes = Config.class)? - Config class will not be registered as a bean.
- Why is useDefaultFilters = false needed? - To ignore standard @Component and scan only custom annotations.
Red flags (DO NOT say):
- “ComponentScan loads all classes via reflection” - no, ASM reads bytecode without loading.
- “You always need to configure @ComponentScan manually” - @SpringBootApplication already scans.
- “spring-context-indexer is a runtime optimization” - no, index is created at compile time.
- “basePackages is safer than basePackageClasses” - opposite, basePackageClasses catches errors at compile time.
Related topics:
- [[21. How SpringBootApplication works]]
- [[25. Difference between Component Service Repository Controller]]
- [[24. What is a Configuration class]]
- [[26. What does the Autowired annotation do]]