Как сканировать несколько путей с помощью аннотации @ComponentScan?


89

Я использую Spring 3.1 и развернув приложение , использующее @Configurationи @ComponentScanатрибуты.

Фактический запуск выполняется с помощью

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Этот класс конфигурации помечен

@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass

и это прекрасно работает. Однако я хотел бы уточнить пакеты, которые я сканирую, поэтому я попытался.

@Configuration
@ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass

Однако это не удается с ошибками, говорящими мне, что он не может найти компоненты, указанные с помощью @Componentаннотации.

Как правильно делать то, что мне нужно?

Благодарность


Насколько я могу судить, два правильных ответа даны примерно в одно время. Я согласен с Хаге только потому, что у него меньше очков, но спасибо вам обоим.
Programming Guy

Если вам интересно то же самое для версии kotlin, проверьте это stackoverflow.com/a/62818187/7747942
Sylhare

Ответы:


159

@ComponentScan использует массив строк, например:

@ComponentScan({"com.my.package.first","com.my.package.second"})

Когда вы указываете несколько имен пакетов только в одной строке, Spring интерпретирует это как одно имя пакета и поэтому не может его найти.


48

Существует еще одна безопасная для типов альтернатива указанию местоположения базового пакета как String. См. API здесь , но я также проиллюстрировал ниже:

@ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})

Использование спецификатора basePackageClasses с вашими ссылками на классы укажет Spring сканировать эти пакеты (как и упомянутые альтернативы ), но этот метод является типобезопасным и добавляет поддержку IDE для будущего рефакторинга - огромный плюс в моей книге.

При чтении из API Spring предлагает создать класс маркера без операции или интерфейс в каждом пакете, который вы хотите сканировать, который не служит никакой другой цели, кроме использования в качестве ссылки для этого атрибута.

ИМО, мне не нравятся классы-маркеры (но опять же, они во многом похожи на классы информации о пакете), но безопасность типов, поддержка IDE и резкое сокращение количества базовых пакетов, необходимых для включения в это сканирование это, без сомнения, гораздо лучший вариант.


Может ли кто-нибудь объяснить, почему @ComponentScan ({"com.app", "com.controllers"}) не работает для меня, но @ComponentScan (basePackageClasses = {"com.controllers"}) работает хорошо? Мне скучно писать каждое имя класса
xaverras 08

3
Вам нужно указать только один класс в пакете для пакета, который вы хотите просканировать. Это называется классом маркера. Если вам нужно сканировать пакет выше в иерархии, который не имеет классов, Spring предлагает метод, использующий интерфейс «маркер пружины» или конечный класс, определенный в этом пакете, исключительно с целью сканирования пакетов.
Prancer

17

Укажите имя вашего пакета отдельно, String[]для имен пакетов требуется .

Вместо этого:

@ComponentScan("com.my.package.first,com.my.package.second")

Использовать это:

@ComponentScan({"com.my.package.first","com.my.package.second"})

10

Другой способ сделать это - использовать basePackagesполе; который является полем внутри аннотации ComponentScan.

@ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})

Если вы посмотрите на аннотацию ComponentScan .class из файла jar, вы увидите поле basePackages, которое принимает массив строк

public @interface ComponentScan {
String[] basePackages() default {};
}

Или вы можете явно указать классы. Которая принимает массив классов

Class<?>[]  basePackageClasses

4

Вы используете ComponentScan для сканирования нескольких пакетов с помощью

@ComponentScan({"com.my.package.first","com.my.package.second"})


1

убедитесь, что вы добавили эту зависимость в свой pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Спасибо, потратив почти полчаса, это была недостающая зависимость
DvixExtract

1

Я использую:

@ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})

0

Вы также можете использовать аннотацию @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })

4
Пожалуйста, подумайте о добавлении пояснений к своему ответу
да,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.