Что делает аннотация @ComponentScan в Spring и как её использовать?

Ответ

@ComponentScan — это аннотация Spring, которая автоматически обнаруживает и регистрирует Spring-компоненты (бины) в контексте приложения, сканируя указанные пакеты.

Как работает:

  1. Сканирует классы в указанных пакетах.
  2. Находит классы, помеченные стереотипными аннотациями:
    • @Component
    • @Service
    • @Repository
    • @Controller
    • @Configuration
  3. Регистрирует их как бины в ApplicationContext.

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

@Configuration
@ComponentScan("com.example.service", "com.example.repository")
public class AppConfig {
    // Дополнительная конфигурация бинов
}

Расширенные настройки:

@Configuration
@ComponentScan(
    basePackages = {"com.example"},
    basePackageClasses = {UserService.class}, // Пакет этого класса будет базовым
    includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Service"),
    excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Repository.class)
)
public class AppConfig {}

Ключевые моменты:

  • Spring Boot: Аннотация @SpringBootApplication уже включает @ComponentScan, сканируя пакет, в котором находится главный класс, и все его подпакеты.
  • Производительность: Избыточное сканирование больших пакетов может замедлить запуск приложения.
  • Конфликты: Может привести к дублированию бинов, если сканируются пересекающиеся области.
  • Альтернатива: Для точного контроля можно регистрировать бины вручную с помощью @Bean в классах конфигурации.

Ответ 18+ 🔞

Да ты посмотри, какая хитрая жопа эта аннотация @ComponentScan! Это ж, блядь, главный шпион Spring'а, который по всем пакетам шарится, как маньяк с фонариком, и выискивает, кого бы в рабы контексту приложения записать.

Как она охуевает от своей работы:

  1. Берёт указанные папки-пакеты и начинает в них рыться.
  2. Находит классы, помеченные особыми метками-аннотациями:
    • @Component (базовая, типа "я компонент, ёпта")
    • @Service (типа "я тут бизнес-логику мучаю")
    • @Repository (этот с базой данных возится)
    • @Controller (этот запросы от клиентов ловит)
    • @Configuration (а этот другим бинам указки раздаёт)
  3. Всё, что нашла — хвать, и в ApplicationContext суёт, как бин. Теперь это управляемые сущности, мать их.

Простой пример, чтоб не еб@ть мозг:

@Configuration
@ComponentScan("com.example.service", "com.example.repository")
public class AppConfig {
    // Тут можно ещё своих ручных бинов накрутить
}

А вот если хочется поизвращаться с фильтрами, будь добр:

@Configuration
@ComponentScan(
    basePackages = {"com.example"},
    basePackageClasses = {UserService.class}, // Сканируй оттуда, где этот класс лежит
    includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Service"), // Бери только то, что в названии "Service"
    excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Repository.class) // А всё, что @Repository, нахуй не надо
)
public class AppConfig {}

Важные нюансы, а то охуеешь потом:

  • В Spring Boot: Аннотация @SpringBootApplication уже включает в себя этот самый @ComponentScan. Она сканирует пакет главного класса и все вложенные папки. Удобно, блядь, но иногда слишком агрессивно.
  • Производительность: Если указать сканировать корень проекта ("com"), а там овердохуища классов, то запуск приложения будет тормозить, как старая кобыла. Указывай точечно.
  • Конфликты: Может случиться пиздец, если два скана находят один и тот же класс — будут два одинаковых бина, и Spring начнёт ныть, что не знает, какой выбрать.
  • Альтернатива: Если не доверяешь этой автоматической шпионке, можно всё делать вручную, объявляя бины через @Bean в классах конфигурации. Полный контроль, но и возни, блядь, дохуя.