@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
в любом компоненте конфигурации, который зарегистрирован в контейнере пружины. Вы можете зарегистрировать компонент в контейнере любым из следующих способов:
- Зарегистрироваться
@Configuration
боб вrootcontext
или жеdispatchersevletcontext
, - Чтобы импортировать это
@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 - просто пример того, что может сделать весна.