Wie scanne ich mehrere Pfade mit der Annotation @ComponentScan?

87

Ich verwende Spring 3.1 und boote eine Anwendung mit den Attributen @Configurationund @ComponentScan.

Der eigentliche Start ist erledigt mit

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Diese Konfigurationsklasse ist mit Anmerkungen versehen

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

und das funktioniert gut. Ich möchte jedoch genauer auf die Pakete eingehen, die ich scanne, also habe ich es versucht.

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

Dies schlägt jedoch mit Fehlern fehl, die darauf hinweisen, dass die mit der @ComponentAnmerkung angegebenen Komponenten nicht gefunden werden können .

Was ist der richtige Weg, um das zu tun, wonach ich suche?

Vielen Dank

Programmierer
quelle
Soweit ich das beurteilen kann, werden zwei richtige Antworten ungefähr zur gleichen Zeit gegeben. Ich werde das Akzeptieren geben, nur weil er weniger Punkte hat, aber ich danke Ihnen beiden.
Programmier Guy
Wenn Sie sich das Gleiche für die Kotlin- Version fragen, überprüfen Sie diese auf stackoverflow.com/a/62818187/7747942
Sylhare

Antworten:

152

@ComponentScan verwendet ein String-Array wie folgt :

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

Wenn Sie mehrere Paketnamen in nur einer Zeichenfolge angeben, interpretiert Spring dies als einen Paketnamen und kann ihn daher nicht finden.

hage
quelle
48

Es gibt eine andere typsichere Alternative zur Angabe eines Basispaketstandorts als Zeichenfolge. Siehe die API hier , aber ich habe auch unten illustriert:

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

Wenn Sie den basePackageClasses-Bezeichner mit Ihren Klassenreferenzen verwenden, wird Spring angewiesen , diese Pakete zu scannen (genau wie die genannten Alternativen ). Diese Methode ist jedoch sowohl typsicher als auch bietet zusätzliche IDE-Unterstützung für zukünftigen Refactoring - ein großes Plus in meinem Buch.

Ausgehend von der API schlägt Spring vor, in jedem Paket, das Sie scannen möchten, eine No-Op-Marker-Klasse oder -Schnittstelle zu erstellen, die keinem anderen Zweck dient, als als Referenz für / von diesem Attribut verwendet zu werden.

IMO, ich mag die Marker-Klassen nicht (aber andererseits sind sie ziemlich genau wie die Paket-Info-Klassen), aber die Typensicherheit, die IDE-Unterstützung und die drastische Reduzierung der Anzahl der Basispakete , die für diesen Scan benötigt werden ist ohne Zweifel eine weitaus bessere Option.

Prancer
quelle
Könnte jemand erklären, warum @ComponentScan ({"com.app", "com.controllers"}) für mich nicht funktioniert, aber @ComponentScan (basePackageClasses = {"com.controllers"}) gut funktioniert? Ich finde es langweilig, jeden Klassennamen zu schreiben
xaverras
3
Sie müssen nur eine Klasse im Paket für das Paket angeben, das Sie scannen möchten. Dies ist als Markerklasse bekannt. Wenn Sie ein Paket höher in der Hierarchie scannen müssen, das keine Klassen enthält, schlägt spring eine Technik vor, die eine "Spring Marker" -Schnittstelle oder eine endgültige Klasse verwendet, die in diesem Paket ausschließlich zum Zweck des Paket-Scannens definiert ist.
Prancer
17

Geben Sie Ihren Paketnamen separat an. String[]Für Paketnamen ist ein Paketname erforderlich .

An Stelle von:

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

Benutze das:

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

Eine andere Möglichkeit, dies zu tun, ist die Verwendung des basePackagesFeldes. Dies ist ein Feld innerhalb der ComponentScan-Annotation.

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

Wenn Sie sich die ComponentScan-Annotation .class aus der JAR-Datei ansehen, sehen Sie ein basePackages-Feld, das ein Array von Strings enthält

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

Oder Sie können die Klassen explizit erwähnen. Welches in Reihe von Klassen nimmt

Class<?>[]  basePackageClasses
shashwatZing
quelle
4

Mit ComponentScan scannen Sie mehrere Pakete mit

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

ksw
quelle
1

Stellen Sie sicher, dass Sie diese Abhängigkeit in Ihrer pom.xml hinzugefügt haben

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Amirtha Krishnan
quelle
Vielen Dank nach fast einer halben Stunde war dies die fehlende Abhängigkeit
DvixExtract
1

Ich benutze:

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

Sie können auch die Annotation @ComponentScans verwenden:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
quelle
4
Bitte erwägen Sie, Ihrer Antwort eine Erklärung hinzuzufügen
yeya