Question 23 · Section 5

What Does the @ComponentScan Annotation Do?

4. excludeFilters -> for tests 5. useDefaultFilters = false -> custom annotations 6. ASM -> does not load classes, reads bytecode

Language versions: English Russian Ukrainian

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

  1. basePackageClasses -> type-safe
  2. spring-context-indexer -> for large projects
  3. Limit packages -> do not scan unnecessary
  4. excludeFilters -> for tests
  5. useDefaultFilters = false -> custom annotations
  6. 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]]