@ComponentScan с несколькими классами конфигурации: конфигурация на основе аннотаций

Согласно весеннему документу

Настраивает директивы сканирования компонентов для использования с классами @Configuration. Обеспечивает поддержку параллельно с Spring XML <context:component-scan> элемент.

В моем весеннем веб-приложении есть несколько файлов, помеченных @Configuration, чтобы зарегистрироваться @component фасоль в весеннем контейнере

Вопрос1- Можем ли мы использовать @ComponentScan в любом из @Configuration класс или во всех @Configuration классы?

Вопрос 2-

Тоже я видела весной док

@Configuration
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {
...
}

Зачем здесь сканирование на предмет конфигурации самого класса.

редактировать: в основном мое понимание с @ComponentScan должен сканировать и регистрировать бин стерео типа (например, @componant,@Controller,@Services и т.д..), почему мы регистрируемся @Configuration Bean.

3 ответа

Решение

На ваш вопрос 1 -

да, вы можете зарегистрировать бин используя @ComponentScan в любом компоненте конфигурации, который зарегистрирован в контейнере пружины. Вы можете зарегистрировать компонент в контейнере любым из следующих способов:

  1. Зарегистрироваться @Configuration боб в rootcontext или жеdispatchersevletcontext,
  2. Чтобы импортировать это @Configuration в бобе, который уже зарегистрирован в контейнере.

Пусть говорят- у вас есть MvcConfig класс, в котором вы сканируете компонент-

@ComponentScan(basePackages = {"xxxx","yyyy","zzzz"})
@Configuration
public class MvcConfig  {
....
}

Зарегистрироваться MvcConfig в контейнере вы должны сделать

Или

new AnnotationConfigWebApplicationContext().register(MvcConfig.class);

Или же

new AnnotationConfigWebApplicationContext().register(AnotherConfig.class);

@Configuration
@Import({MvcConfig.class})
public class AnotherConfig  {
....
}

На ваш вопрос 2 -

Здесь весна не только регистрируется MyConfiguration.class но и все классы компонентов, которые присутствуют в пакете, в котором MyConfiguration определены.

Решение вопроса 1:
Да, вы можете использовать @Componentscan в столько же классов конфигурации. Это все зависит от вас. Он просто регистрирует различные аннотированные классы некоторых конкретных пакетов как бины. Так что, если у вас есть все компоненты аннотированных классов, отсканированные одним @Componentscan, этого достаточно, так как все требуемые компоненты были активированы и зарегистрированы в контейнере DispatcherServlet.

Решение вопроса 2:

@Configuration
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {
...
}

Ваш вопрос: зачем здесь сканирование для самого класса конфигурации?
это @ComponentScan(basePackageClasses = { MyConfiguration.class }) упоминает MyConfiguration.class в качестве примера. Вопрос в том, что это значит?

Компоненты могут проверять пакеты двумя способами: basepackage атрибут или basepackageclasses, Эти два одинаковы, но используют basepackageclasses имеет два преимущества:
Он безопасен по типу и добавляет поддержку IDE для будущего рефакторинга
Это просто означает, что в будущем вы можете переименовать (с помощью рефакторинга) некоторые базовые бэкапы, и, поскольку вы переименовали базовые пакеты, вам не нужно менять @ComponentScan в ваших классах конфигурации, если вы использовали basepackageclasses приписывать.

Теперь вернемся к вашему второму вопросу. Почему MyConfiguration.class указывается в качестве значения basepackageclasses атрибут @Componentscan?

Прежде всего, дайте нам знать это:
basepackageclasses Атрибут принимает строковое значение, которое представляет некоторый класс маркера. Этот класс Маркер говорит: Эй! зарегистрировать все классы, присутствующие в пакете, в котором присутствует этот класс, включая этот класс

Итак, здесь, в вашем ответе, будут проверены все те классы, которые присутствуют в пакете, в котором присутствует MyConfiguration.class.

Следовательно, Myconfiguration.class действует как класс Configuration, а также как маркерный класс для сканирования компонентов других классов. Это также подразумевает, что все аннотированные классы будут зарегистрированы, которые присутствуют в пакете, в котором присутствует MyConfiguration.class, включая MyConfiguration.class, так как он аннотирован аннотацией @Configuration.

basepackageclasses Атрибут может иметь и другие классы, такие как com.abc.org.Marker.class

Выгода:
Таким образом, если вы переименуете пакеты, проблем не возникнет, так как у вас есть классы маркеров, которые помогают Spring найти пакеты. Эти классы маркеров могут иметь или не иметь никакого содержимого внутри, поскольку они просто действуют как маркер для поиска пакетов.

Из документации:

Q1:

@Configuration мета-аннотируется с помощью @Component, поэтому классы @Configuration являются кандидатами для сканирования компонентов (обычно с использованием элемента Spring XML) и, следовательно, могут также использовать преимущества @Autowired/@Inject, как и любой обычный @Component.

Классы @Configuration могут не только загружаться с использованием компонентного сканирования, но и сами настраивать сканирование компонентов с помощью аннотации @ComponentScan:

@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
 // various @Bean definitions ...
}

Q2:

basePackageClasses

public abstract Class<?>[] basePackageClasses

Типобезопасная альтернатива basePackages() для указания пакетов для сканирования аннотированных компонентов. Пакет каждого указанного класса будет проверен.


Ответ на ваш отредактированный вопрос

В какой-то момент вы должны сказать Spring, где находятся компоненты вашего приложения. Вы можете использовать, например:

public static void main(String[] args) {  
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");  
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}

или используя старый стиль XML:

<context:component-scan base-package="com.acme" />

Используя @ComponentScan на уровне @Configuration, вы убедитесь, что все зависимости для этого класса конфигурации будут доступны. Используя @CompenentScan с basePackageClasses, вы регистрируете все компоненты, доступные в том же пакете, что и указанный класс.

Если вы уже сообщили Spring, какие пакеты нужно сканировать, в другом месте или в другом месте, вам не нужно его использовать. Кусок кода в вашем Q2 - просто пример того, что может сделать весна.

Другие вопросы по тегам