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

Programista
źródło
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źć.

hage
źródło
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ą.

Prancer
źródło
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"})
mprabhat
źródło
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
shashwatZing
źródło
4

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

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

ksw
źródło
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>
Amirtha Krishnan
źródło
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"})
Yann
źródło
0

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

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
źródło
4
Proszę rozważyć dodanie wyjaśnienia do swojej odpowiedzi
yeya