Scannen von Federkomponenten

1. Übersicht

In diesem Tutorial behandeln wir das Scannen von Komponenten im Frühjahr. Wenn wir mit Spring arbeiten, können wir unsere Klassen mit Anmerkungen versehen, um sie zu Spring Beans zu machen. Abgesehen davon können wir Spring jedoch mitteilen, wo nach diesen mit Anmerkungen versehenen Klassen gesucht werden soll, da nicht alle in diesem bestimmten Lauf zu Bohnen werden müssen.

Natürlich gibt es einige Standardeinstellungen für das Scannen von Komponenten, aber wir können die Pakete auch für die Suche anpassen.

Schauen wir uns zunächst die Standardeinstellungen an.

2. @ComponentScan Ohne Argumente

2.1. Verwenden von @ComponentScan in einer Spring-Anwendung

In Spring verwenden wir die Annotation @ComponentScan zusammen mit der Annotation @Configuration , um die Pakete anzugeben, die gescannt werden sollen . @ComponentScan ohne Argumente weist Spring an, das aktuelle Paket und alle seine Unterpakete zu scannen.

Lassen Sie uns sagen , dass wir die folgende haben @Configuration in com.baeldung.componentscan.springapp Paket:

@Configuration @ComponentScan public class SpringComponentScanApp { private static ApplicationContext applicationContext; @Bean public ExampleBean exampleBean() { return new ExampleBean(); } public static void main(String[] args) { applicationContext = new AnnotationConfigApplicationContext(SpringComponentScanApp.class); for (String beanName : applicationContext.getBeanDefinitionNames()) { System.out.println(beanName); } } }

Auch lassen Sie uns sagen , dass wir die haben Katze und Hund Komponenten in com.baeldung.componentscan.springapp.animals Paket:

package com.baeldung.componentscan.springapp.animals; // ... @Component public class Cat {}
package com.baeldung.componentscan.springapp.animals; // ... @Component public class Dog {}

Und schließlich haben wir die Rose- Komponente im Paket com.baeldung.componentscan.springapp.flowers :

package com.baeldung.componentscan.springapp.flowers; // ... @Component public class Rose {}

Die Ausgabe der main () -Methode enthält alle Beans des com.baeldung.componentscan.springapp- Pakets und seiner Unterpakete :

springComponentScanApp cat dog rose exampleBean

Beachten Sie, dass die Hauptanwendungsklasse auch eine Bean ist, da sie mit @Configuration, einer @Component , kommentiert ist .

Beachten Sie außerdem, dass die Hauptanwendungsklasse und die Konfigurationsklasse nicht unbedingt identisch sind. Wenn sie unterschiedlich sind, spielt es keine Rolle, wo die Hauptanwendungsklasse abgelegt werden soll. Nur der Speicherort der Konfigurationsklasse ist von Bedeutung, da das Scannen von Komponenten standardmäßig von ihrem Paket aus beginnt .

Beachten Sie schließlich, dass in unserem Beispiel @ComponentScan gleichbedeutend ist mit:

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp")

Dabei ist das Argument basePackages ein Paket oder ein Array von Paketen zum Scannen.

2.2. Verwenden von @ComponentScan in einer Spring Boot-Anwendung

Der Trick bei Spring Boot ist, dass viele Dinge implizit passieren. Wir verwenden die Annotation @SpringBootApplication , aber es ist nur eine Kombination aus drei Annotationen:

@Configuration @EnableAutoConfiguration @ComponentScan

Erstellen wir eine ähnliche Struktur im Paket com.baeldung.componentscan.springbootapp . Diesmal ist die Hauptanwendung:

package com.baeldung.componentscan.springbootapp; // ... @SpringBootApplication public class SpringBootComponentScanApp { private static ApplicationContext applicationContext; @Bean public ExampleBean exampleBean() { return new ExampleBean(); } public static void main(String[] args) { applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args); checkBeansPresence( "cat", "dog", "rose", "exampleBean", "springBootComponentScanApp"); } private static void checkBeansPresence(String... beans) { for (String beanName : beans) { System.out.println("Is " + beanName + " in ApplicationContext: " + applicationContext.containsBean(beanName)); } } }

Alle anderen Pakete und Klassen bleiben gleich. Wir kopieren sie einfach in das nahe gelegene Paket com.baeldung.componentscan.springbootapp .

Spring Boot scannt Pakete ähnlich wie in unserem vorherigen Beispiel. Lassen Sie uns die Ausgabe überprüfen:

Is cat in ApplicationContext: true Is dog in ApplicationContext: true Is rose in ApplicationContext: true Is exampleBean in ApplicationContext: true Is springBootComponentScanApp in ApplicationContext: true

Der Grund, warum wir in unserem zweiten Beispiel nur die Existenz der Beans überprüfen (im Gegensatz zum Ausdrucken aller Beans), ist, dass die Ausgabe zu groß wäre.

Dies liegt an der impliziten Annotation @EnableAutoConfiguration, mit der Spring Boot viele Beans automatisch erstellt, abhängig von den Abhängigkeiten in der Datei pom.xml .

3. @ComponentScan mit Argumenten

Passen wir nun die Pfade für das Scannen an. Nehmen wir zum Beispiel an, wir möchten die Rose Bean ausschließen.

3.1. @ComponentScan für bestimmte Pakete

Wir können es auf verschiedene Arten tun. Zunächst können wir das Basispaket ändern:

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals") @Configuration public class SpringComponentScanApp {   // ... }

Jetzt wird die Ausgabe sein:

springComponentScanApp cat dog exampleBean

Mal sehen, was dahinter steckt:

  • springComponentScanApp wird als Konfiguration erstellt, die als Argument an den AnnotationConfigApplicationContext übergeben wird
  • exampleBean ist eine Bean, die in der Konfiguration konfiguriert ist
  • Katze und Hund befinden sich im angegebenen Paket com.baeldung.componentscan.springapp.animals

Alle oben aufgeführten Anpassungen gelten auch für Spring Boot. Wir können @ComponentScan zusammen mit @SpringBootApplication verwenden und das Ergebnis ist das gleiche:

@SpringBootApplication @ComponentScan(basePackages = "com.baeldung.componentscan.springbootapp.animals")

3.2. @ComponentScan mit Ausschlüssen

Eine andere Möglichkeit besteht darin, einen Filter zu verwenden, der das Muster angibt, das die Klassen ausschließen sollen:

@ComponentScan(excludeFilters = @ComponentScan.Filter(type=FilterType.REGEX, pattern="com\\.baeldung\\.componentscan\\.springapp\\.flowers\\..*"))

Wir können auch einen anderen Filtertyp auswählen, da die Anmerkung mehrere flexible Optionen zum Filtern der gescannten Klassen unterstützt :

@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Rose.class))

4. Das Standardpaket

Wir sollten vermeiden, die @ Configuration- Klasse in das Standardpaket aufzunehmen (dh das Paket überhaupt nicht anzugeben). In diesem Fall scannt Spring alle Klassen in allen Gläsern in einem Klassenpfad. Das verursacht Fehler und die Anwendung startet wahrscheinlich nicht.

5. Schlussfolgerung

In diesem Artikel haben wir erfahren, welche Pakete Spring standardmäßig scannt und wie diese Pfade angepasst werden.

Wie üblich ist der vollständige Code auf GitHub verfügbar.