1. Обзор
В этом уроке мы рассмотрим сканирование компонентов весной. При работе с Spring мы можем аннотировать наши классы, чтобы превратить их в весенние бобы. Но, кроме того, мы можем сказать Spring, где искать эти аннотированные классы , поскольку не все из них должны стать бобами в этом конкретном запуске.
Конечно, существуют некоторые настройки по умолчанию для сканирования компонентов, но мы также можем настроить пакеты для поиска.
Во-первых, давайте рассмотрим настройки по умолчанию.
Дальнейшее чтение:
Аннотации к весенним бобам
Spring @ComponentScan – Типы фильтров
Создайте пользовательскую автоматическую конфигурацию с помощью Spring Boot
2. @ComponentScan Без Аргументов
2.1. Использование @ComponentScan в приложении Spring
В Spring мы используем аннотацию @ComponentScan вместе с аннотацией @Configuration , чтобы указать пакеты, которые мы хотим сканировать . |/@ComponentScan без аргументов говорит Spring сканировать текущий пакет и все его подпакеты.
Допустим, у нас есть следующий @Configuration in com.baeldung.components can.springapp package:
@Configuration @ComponentScan public class SpringComponentScanApp { private static ApplicationContext applicationContext; @Bean public ExampleBean exampleBean() { return new ExampleBean(); } public static void main(String[] args) { applicationContext = new AnnotationConfigApplicationContext(SpringComponentScanApp.class); for (String beanName : applicationContext.getBeanDefinitionNames()) { System.out.println(beanName); } } }
Кроме того, предположим, что у нас есть компоненты Cat и Dog в com.baeldung.components can.springapp.animals package:
package com.baeldung.componentscan.springapp.animals; // ... @Component public class Cat {}
package com.baeldung.componentscan.springapp.animals; // ... @Component public class Dog {}
И, наконец, у нас есть компонент Rose в com.baeldung.components can.springapp.flowers package:
package com.baeldung.componentscan.springapp.flowers; // ... @Component public class Rose {}
Выходные данные метода main() будут содержать все компоненты пакета com.baeldung.componentscan.springapp и его подпакетов:
springComponentScanApp cat dog rose exampleBean
Обратите внимание, что основной класс приложения также является бобом, поскольку он аннотирован @Configuration, который является @Component .
Кроме того, обратите внимание, что основной класс приложения и класс конфигурации не обязательно совпадают. Если они разные, не имеет значения, куда поместить основной класс приложения. Значение имеет только расположение класса конфигурации, поскольку сканирование компонентов по умолчанию начинается с его пакета .
Наконец, обратите внимание, что в нашем примере @ComponentScan эквивалентно:
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp")
где basePackages аргумент-это пакет или массив пакетов для сканирования.
2.2. Использование @ComponentScan в приложении Spring Boot
Трюк с Spring Boot заключается в том, что многие вещи происходят неявно. Мы используем аннотацию @SpringBootApplication , но это всего лишь комбинация трех аннотаций:
@Configuration @EnableAutoConfiguration @ComponentScan
Давайте создадим аналогичную структуру в com.baeldung.componentscan.spring boot app package. На этот раз основным приложением будет:
package com.baeldung.componentscan.springbootapp; // ... @SpringBootApplication public class SpringBootComponentScanApp { private static ApplicationContext applicationContext; @Bean public ExampleBean exampleBean() { return new ExampleBean(); } public static void main(String[] args) { applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args); checkBeansPresence( "cat", "dog", "rose", "exampleBean", "springBootComponentScanApp"); } private static void checkBeansPresence(String... beans) { for (String beanName : beans) { System.out.println("Is " + beanName + " in ApplicationContext: " + applicationContext.containsBean(beanName)); } } }
Все остальные пакеты и классы остаются прежними, мы просто скопируем их в ближайший com.baeldung.components can.springbootapp пакет.
Spring Boot сканирует пакеты аналогично нашему предыдущему примеру. Давайте проверим вывод:
Is cat in ApplicationContext: true Is dog in ApplicationContext: true Is rose in ApplicationContext: true Is exampleBean in ApplicationContext: true Is springBootComponentScanApp in ApplicationContext: true
Причина, по которой мы просто проверяем бобы на наличие в нашем втором примере (в отличие от печати всех бобов), заключается в том, что вывод будет слишком большим.
Это происходит из-за неявной аннотации @EnableAutoConfiguration , которая заставляет Spring Boot автоматически создавать множество компонентов, полагаясь на зависимости в pom.xml файл.
3. @ComponentScan С Аргументами
Теперь давайте настроим пути для сканирования. Например, предположим, что мы хотим исключить Rose bean.
3.1. @ComponentScan для конкретных пакетов
Мы можем сделать это несколькими способами. Во-первых, мы можем изменить базовый пакет:
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals") @Configuration public class SpringComponentScanApp { // ... }
Теперь выход будет:
springComponentScanApp cat dog exampleBean
Давайте посмотрим, что за этим стоит:
- springComponentScanApp создается как конфигурация, передаваемая в качестве аргумента в текст AnnotationConfigApplicationContext
- exampleBean – это компонент, настроенный внутри конфигурации
- кошка и собака находятся в указанном com.baeldung.components can.springapp.animals пакете
Все вышеперечисленные настройки применимы и в Spring Boot. Мы можем использовать @ComponentScan вместе с @SpringBootApplication , и результат будет таким же:
@SpringBootApplication @ComponentScan(basePackages = "com.baeldung.componentscan.springbootapp.animals")
3.2. @ComponentScan с исключениями
Другой способ – использовать фильтр, указывающий шаблон для исключаемых классов:
@ComponentScan(excludeFilters = @ComponentScan.Filter(type=FilterType.REGEX, pattern="com\\.baeldung\\.componentscan\\.springapp\\.flowers\\..*"))
Мы также можем выбрать другой тип фильтра, так как аннотация поддерживает несколько гибких вариантов фильтрации отсканированных классов :
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Rose.class))
4. Пакет по Умолчанию
Мы должны избегать помещения @Configuration class в пакет по умолчанию (т. Е. Вообще не указывая пакет). В этом случае Spring сканирует все классы во всех банках в пути к классам. Это приводит к ошибкам, и приложение, вероятно, не запускается.
5. Заключение
В этой статье мы узнали, какие пакеты Spring сканирует по умолчанию и как настроить эти пути.
Как обычно, полный код доступен на GitHub .