Jak skanować wiele ścieżek za pomocą adnotacji @ComponentScan?


89

Używam Spring 3.1 i ładuję aplikację przy użyciu atrybutów @Configurationi @ComponentScan.

Właściwy start jest zakończony

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Ta klasa konfiguracji jest opatrzona adnotacją

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

i to działa dobrze. Chciałbym jednak bardziej szczegółowo opisać pakiety, które skanuję, więc spróbowałem.

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

Jednak kończy się to niepowodzeniem z błędami informującymi mnie, że nie może znaleźć komponentów określonych za pomocą @Componentadnotacji.

Jaki jest właściwy sposób robienia tego, czego szukam?

Dzięki


Dwie poprawne odpowiedzi udzielone mniej więcej w tym samym czasie, o ile wiem. Zgadzam się z hage tylko dlatego, że ma mniej punktów, ale dziękuję wam obojgu.
Programming Guy

Jeśli zastanawiasz się nad tym samym w przypadku wersji kotlin, sprawdź to stackoverflow.com/a/62818187/7747942
Sylhare

Odpowiedzi:


159

@ComponentScan używa tablicy ciągów, takiej jak ta:

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

Jeśli podasz wiele nazw pakietów w jednym ciągu, Spring interpretuje to jako jedną nazwę pakietu i dlatego nie może go znaleźć.


48

Istnieje inna bezpieczna dla typu alternatywa dla określania lokalizacji pakietu podstawowego jako String. Zobacz API tutaj , ale zilustrowałem również poniżej:

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

Użycie specyfikatora basePackageClasses z odwołaniami do klas powie Springowi, aby przeskanował te pakiety (tak jak wspomniane alternatywy ), ale ta metoda jest zarówno bezpieczna dla typów, jak i dodaje obsługę IDE dla przyszłych refaktoryzacji - ogromny plus w mojej książce.

Czytając z interfejsu API, Spring sugeruje utworzenie klasy lub interfejsu znacznika no-op w każdym pakiecie, który chcesz skanować, który służy wyłącznie do wykorzystania jako odniesienie dla / przez ten atrybut.

IMO, nie lubię klas znaczników (ale z drugiej strony są one prawie takie same jak klasy informacji o pakiecie), ale bezpieczeństwo typów, obsługa IDE i drastyczne zmniejszenie liczby pakietów podstawowych potrzebnych do tego skanowania jest bez wątpienia znacznie lepszą opcją.


Czy ktoś mógłby wyjaśnić, dlaczego @ComponentScan ({"com.app", "com.controllers"}) nie działa dla mnie, ale @ComponentScan (basePackageClasses = {"com.controllers"}) działa dobrze? Uważam, że pisanie każdej nazwy zajęć jest nudne
xaverras

3
Musisz tylko określić jedną klasę w pakiecie dla pakietu, który chcesz przeskanować. Jest to znane jako klasa znaczników. Jeśli potrzebujesz przeskanować pakiet znajdujący się wyżej w hierarchii, który nie ma klas, spring sugeruje technikę wykorzystującą interfejs „marker sprężyny” lub klasę końcową zdefiniowaną w tym pakiecie wyłącznie w celu skanowania pakietów.
Prancer,

17

Podaj nazwę pakietu osobno, wymaga to String[] dla nazw pakietów.

Zamiast tego:

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

Użyj tego:

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

10

Innym sposobem na to jest użycie basePackagespola; czyli pole wewnątrz adnotacji ComponentScan.

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

Jeśli spojrzysz na adnotację ComponentScan .class z pliku jar, zobaczysz pole basePackages, które przyjmuje tablicę ciągów znaków

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

Możesz też wyraźnie wspomnieć o klasach. Który przyjmuje szereg klas

Class<?>[]  basePackageClasses

4

ComponentScan służy do skanowania wielu pakietów za pomocą

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


1

upewnij się, że dodałeś tę zależność w swoim pom.xml

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

Dzięki spędzeniu blisko pół godziny to była brakująca zależność
DvixExtract

1

Używam:

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

0

Możesz również użyć adnotacji @ComponentScans:

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

4
Proszę rozważyć dodanie wyjaśnienia do swojej odpowiedzi
yeya
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.