Що робить анотація @ComponentScan?
4. excludeFilters → для тестів 5. useDefaultFilters = false → кастомні анотації 6. ASM → не завантажує класи, читає байт-код
🟢 Junior Level
@ComponentScan — вказує Spring, в яких пакетах шукати біни (@Component, @Service, @Repository).
@SpringBootApplication // Вже включає @ComponentScan
public class Application { }
// Ручне налаштування:
@ComponentScan(basePackages = "com.example.services")
Правило:
- @SpringBootApplication сканує поточний пакет та всі підпакети
- Зазвичай не потрібно налаштовувати вручну
🟡 Middle Level
Як працює сканування
ClassPathBeanDefinitionScanner:
1. Читає .class файли через ASM (бібліотека для читання байт-коду без завантаження класів в JVM)
// Це важливо: класи не проходять повну ініціалізацію JVM, їх static блоки не виконуються.
// Spring тільки читає анотації з .class файлів.
2. Шукає анотації @Component, @Service...
3. Створює BeanDefinition
4. НЕ завантажує класи в JVM!
Налаштування
// Сканувати конкретні пакети
@ComponentScan(basePackages = {"com.example.a", "com.example.b"})
// Типобезпечно (рекомендується!)
@ComponentScan(basePackageClasses = MyMarkerInterface.class)
// Виключити класи
@ComponentScan(excludeFilters = @Filter(Type.ASSIGNABLE_TYPE, classes = Config.class))
spring-context-indexer
Для великих проектів → повільне сканування
Залежність: spring-context-indexer
→ При компіляції створює META-INF/spring.components
→ Spring читає список замість сканування
→ Старт в 2-3 рази швидший!
🔴 Senior Level
ConfigurationClassPostProcessor
Запускає сканування:
1. Парсить @Configuration класи
2. Обробляє @Import
3. Запускає ClassPathBeanDefinitionScanner
4. Реєструє BeanDefinition
Фільтрація
@ComponentScan(
useDefaultFilters = false, // Вимкнути @Component
includeFilters = @Filter(MyCustomAnnotation.class)
)
// Це корисно, якщо ви хочете сканувати тільки свої кастомні анотації
// та ігнорувати стандартні @Component/@Service. Усі стандартні біни
// при цьому НЕ зареєструються!
Production Experience
Реальний сценарій: 10 секунд на сканування
5000 класів → ASM сканування → 10 секунд
Рішення: spring-context-indexer
Результат: 2 секунди
Best Practices
- basePackageClasses → типобезпечно
- spring-context-indexer → для великих проектів
- Обмежте пакети → не скануйте зайве
- excludeFilters → для тестів
- useDefaultFilters = false → кастомні анотації
- ASM → не завантажує класи, читає байт-код
Резюме для Senior
- @ComponentScan → пошук бінів у пакетах
- ASM → читання байт-коду, не рефлексія
- ConfigurationClassPostProcessor → запускає сканування
- spring-context-indexer → прискорення старту
- basePackageClasses → типобезпечно
- Фільтри → include/exclude
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
- @ComponentScan шукає @Component, @Service, @Repository, @Controller у вказаних пакетах
- @SpringBootApplication вже включає @ComponentScan поточного пакета та підпакетів
- ASM читає байт-код .class файлів — класи НЕ завантажуються в JVM, static блоки НЕ виконуються
- ConfigurationClassPostProcessor запускає сканування на ранній фазі
- spring-context-indexer створює META-INF/spring.components при компіляції — старт в 2-3 рази швидший
- basePackageClasses — типобезпечна альтернатива рядковим пакетам
- includeFilters / excludeFilters — тонке налаштування сканування
Часті уточнюючі запитання:
- Чому Spring не завантажує класи при скануванні? — ASM читає тільки анотації з байт-коду, це швидше та безпечніше (static блоки не виконуються).
- Як прискорити сканування у великому проекті? — spring-context-indexer: мета-файл створюється при компіляції, Spring читає його замість обходу classpath.
- Що буде з excludeFilters = @Filter(Type.ASSIGNABLE_TYPE, classes = Config.class)? — Клас Config не буде зареєстрований як бін.
- Навіщо потрібен useDefaultFilters = false? — Щоб ігнорувати стандартні @Component та сканувати тільки кастомні анотації.
Червоні прапорці (НЕ говорити):
- «ComponentScan завантажує всі класи через рефлексію» — ні, ASM читає байт-код без завантаження.
- «Потрібно завжди налаштовувати @ComponentScan вручну» — @SpringBootApplication вже сканує.
- «spring-context-indexer — це runtime-оптимізація» — ні, індекс створюється при компіляції.
- «basePackages безпечніше basePackageClasses» — навпаки, basePackageClasses ловить помилки на компіляції.
Пов’язані теми:
- [[21. Як працює @SpringBootApplication]]
- [[25. В чому різниця між @Component, @Service, @Repository, @Controller]]
- [[24. Що таке @Configuration клас]]
- [[26. Що робить анотація @Autowired]]