Для чего используется аннотация @ComponentScan в Spring?

«Для чего используется аннотация @ComponentScan в Spring?» — вопрос из категории Spring, который задают на 22% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

@ComponentScan — это аннотация Spring Framework, которая инструктирует контейнер IoC, где искать классы, помеченные стереотипными аннотациями (такими как @Component, @Service, @Repository, @Controller, @Configuration), чтобы автоматически зарегистрировать их как бины (beans) в контексте приложения.

Основная цель: Автоматическое обнаружение и регистрация компонентов, избавляющее от необходимости ручного объявления каждого бина с помощью @Bean в конфигурационном классе.

Ключевые параметры аннотации:

  • basePackages / value: Массив имен пакетов для сканирования.
    @ComponentScan({"com.example.service", "com.example.dao"})
  • basePackageClasses: Массив классов. Пакеты этих классов будут использоваться в качестве отправных точек для сканирования. Это типобезопасная альтернатива basePackages.
    @ComponentScan(basePackageClasses = {UserService.class, UserRepository.class})
  • excludeFilters / includeFilters: Позволяют тонко настраивать, какие классы включать или исключать из сканирования, используя аннотации, регулярные выражения и т.д.

Типичное использование:

@Configuration
@ComponentScan("com.example.app") // Сканирует пакет com.example.app и все его подпакеты
public class AppConfig {
    // Дополнительные бины, объявленные вручную
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }
}

Важные детали:

  1. Контекст по умолчанию: Если параметры не указаны, сканирование начинается с пакета, в котором находится класс, помеченный @ComponentScan. Это часто приводит к ошибкам, если конфигурационный класс лежит в корневом пакете.
  2. Область применения: Аннотация используется на классах, помеченных @Configuration или непосредственно на главном классе приложения с аннотацией @SpringBootApplication (которая уже содержит в себе @ComponentScan).
  3. Комбинация с ручной конфигурацией: @ComponentScan можно свободно комбинировать с объявлениями @Bean в одном конфигурационном классе.
  4. Фильтрация: Механизм фильтров (excludeFilters) часто используется в тестах для исключения определенных конфигураций или замены реальных бинов моками.

Пример с фильтром:

@Configuration
@ComponentScan(
    basePackages = "com.example",
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = Repository.class // Исключаем все @Repository из сканирования
    )
)
public class AppConfig { }