Рубрики
Без рубрики

Сканирование пружинных компонентов

Узнайте о механизме сканирования пружинных компонентов и о том, как вы можете настроить его в соответствии со своими потребностями

Автор оригинала: baeldung.

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 .