Как работает аннотация @ComponentScan в Spring Framework?

Ответ

@ComponentScan — это аннотация Spring, которая инструктирует контейнер IoC сканировать классы на наличие Spring-компонентов и автоматически регистрировать их как бины.

Механизм работы:

  1. Стартовая точка: Сканирование начинается с пакета, указанного в basePackages или basePackageClasses. Если пакет не задан, используется пакет класса, аннотированного @ComponentScan.
  2. Поиск компонентов: Spring просматривает все классы в указанных пакетах (и их подпакетах) в classpath.
  3. Идентификация: Классы, аннотированные как @Component, @Service, @Repository, @Controller, @Configuration, обнаруживаются и регистрируются в ApplicationContext.

Пример конфигурации:

@Configuration
@ComponentScan(
    basePackages = {"com.example.service", "com.example.repository"},
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = {Configuration.class}
    )
)
public class AppConfig {}

Ключевые параметры для настройки:

  • basePackages / basePackageClasses: Задает пакеты для сканирования.
  • includeFilters: Позволяет включать классы, даже если у них нет стандартных Spring-аннотаций (например, с помощью кастомных аннотаций).
  • excludeFilters: Позволяет исключать определенные классы из сканирования.

Важно: В Spring Boot @ComponentScan неявно используется аннотацией @SpringBootApplication, которая сканирует все подпакеты от класса с этой аннотацией.

Ответ 18+ 🔞

А, слушай, про эту аннотацию @ComponentScan... Ну, это такая, блядь, волшебная палочка для Спринга, которая вместо тебя бегает по твоим пакетам и кричит: «Эй, ты! Да, ты, класс с аннотацией @Service! Иди сюда, в контекст, будешь бином!». И всё это без твоих кривых рук, которые в XML конфигах бобы прописывают.

Как эта магия, сука, работает:

  1. Откуда начинаем: Всё стартует от пакета, который ты в basePackages указал. Не указал? Ну, тогда Спринг, как хитрая жопа, начнёт рыскать в том же пакете, где лежит класс с этой самой аннотацией @ComponentScan.
  2. Прочёсывание: Дальше он, как заправский маньяк, прочёсывает ВСЕ классы в этих пакетах и подпакетах. Овердохуища классов может быть, но ему похуй.
  3. Опознание: Ищет тех, кто помечен особыми метками: @Component, @Service, @Repository, @Controller. Увидел — хвать! — и уже регистрирует в ApplicationContext. Готово, блядь.

Вот, смотри, как это в коде выглядит:

@Configuration
@ComponentScan(
    basePackages = {"com.example.service", "com.example.repository"},
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = {Configuration.class}
    )
)
public class AppConfig {}

Видишь? Говорим: «Ищи, сука, компоненты в service и repository, но вот эти @Configuration-классы, блядь, не трогай, они тут не при чём».

На что ещё, блядь, можно кнопки нажимать:

  • basePackages / basePackageClasses: Тыкаешь пальцем — вот тут ищи, ёпта. В этих пакетах.
  • includeFilters: Это для особо хитрожопых случаев. Типа: «Вот этот класс, у него даже @Component нет, но он мой, включи его, я так хочу!». Кастомные аннотации, всякое такое.
  • excludeFilters: А это наоборот — «Вот этого пидораса, шерстяного, проигнорируй, пусть не лезет в мой чистый контекст».

И главное, запомни: В Spring Boot тебе эту аннотацию, блядь, даже руками прописывать редко надо. Потому что @SpringBootApplication уже внутри себя её содержит, и сканирует всё от своего пакета и ниже. Удобно, ёпта! Хуй с горы, а не конфигурация.