Вопрос по spring, java – Как сканировать несколько путей, используя аннотацию @ComponentScan?

71

Я использую 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 аннотаций.

Какой правильный способ сделать то, что я делаю после?

Спасибо

Спасибо, Питер :) hage
Насколько я могу судить, два правильных ответа даны примерно одновременно. Я дам согласие на возмущение только потому, что у него меньше очков, но спасибо вам обоим. Peter Wilkinson

Ваш Ответ

6   ответов
3

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

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

124

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

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

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

9

Еще один способ сделать это с помощьюbasePackages поле; которое является полем внутри аннотации ComponentScan.

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

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

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

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

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

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

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

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

Есть еще одноtype-safe alternative чтобы указать расположение базового пакета в виде строки.Смотрите API здесь, но я также проиллюстрирован ниже:

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

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

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

IMO, мне не нравятся классы маркеров(but then again, they are pretty much just like the package-info classes) но безопасность типов, поддержка IDE и резкое сокращение количества базовых пакетов, которые необходимо включить для этого сканирования, - без сомнения, гораздо лучший вариант.

Вам нужно указать только один класс в пакете для пакета, который вы хотите сканировать. Это известно как маркерный класс. Если вам нужно отсканировать пакет выше в иерархии, в которой нет классов, Spring предлагает метод с использованием «маркера весны». интерфейс или конечный класс, определенный в этом пакете исключительно для целей сканирования пакета.
Может ли кто-нибудь объяснить, почему @ComponentScan ({& quot; com.app & quot ;, & quot; com.controllers & quot;}) не работает для меня, но @ComponentScan (basePackageClasses = {& quot; com.controllers & quot;}) работает хорошо? Мне скучно писать каждое название класса
0

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

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Пожалуйста, рассмотрите возможность добавления объяснения к вашему ответу.

Похожие вопросы