Comment scanner plusieurs chemins à l'aide de l'annotation @ComponentScan?

89

J'utilise Spring 3.1 et j'amorce une application à l'aide des attributs @Configurationet @ComponentScan.

Le démarrage réel se fait avec

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Cette classe de configuration est annotée avec

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

et cela fonctionne très bien. Cependant, j'aimerais être plus précis sur les paquets que je scanne alors j'ai essayé.

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

Cependant, cela échoue avec des erreurs me disant qu'il ne peut pas trouver les composants spécifiés à l'aide de l' @Componentannotation.

Quelle est la bonne façon de faire ce que je recherche?

Merci

Guy de programmation
la source
Deux bonnes réponses données à peu près en même temps pour autant que je sache. Je vais accepter de hage juste parce qu'il a moins de points, mais merci à tous les deux.
Programmation Guy
Si vous vous demandez la même chose pour la version kotlin , vérifiez celui-ci stackoverflow.com/a/62818187/7747942
Sylhare

Réponses:

159

@ComponentScan utilise un tableau de chaînes, comme ceci:

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

Lorsque vous fournissez plusieurs noms de package dans une seule chaîne, Spring l'interprète comme un seul nom de package et ne peut donc pas le trouver.

hage
la source
48

Il existe une autre alternative de type sécurisé à la spécification d'un emplacement de package de base sous forme de chaîne. Voir l'API ici , mais j'ai également illustré ci-dessous:

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

L'utilisation du spécificateur basePackageClasses avec vos références de classe indiquera à Spring d'analyser ces packages (tout comme les alternatives mentionnées ), mais cette méthode est à la fois sûre de type et ajoute le support IDE pour la refactorisation future - un énorme plus dans mon livre.

En lisant l'API, Spring suggère de créer une classe ou une interface de marqueur sans opération dans chaque package que vous souhaitez analyser et qui ne sert à rien d'autre que d'être utilisée comme référence pour / par cet attribut.

OMI, je n'aime pas les classes de marqueurs (mais encore une fois, elles ressemblent à peu près aux classes d'informations sur les packages) mais la sécurité de type, le support IDE et la réduction drastique du nombre de packages de base nécessaires à inclure pour cette analyse est, sans aucun doute, une bien meilleure option.

Prancer
la source
Quelqu'un pourrait-il expliquer pourquoi @ComponentScan ({"com.app", "com.controllers"}) ne fonctionne pas pour moi mais @ComponentScan (basePackageClasses = {"com.controllers"}) fonctionne bien? Je trouve ça ennuyeux d'écrire chaque nom de classe
xaverras
3
Vous n'avez qu'à spécifier une classe dans le package, pour le package que vous souhaitez analyser. Ceci est connu comme une classe de marqueurs. Si vous avez besoin d'analyser un package plus haut dans la hiérarchie qui n'a pas de classes, spring suggère une technique utilisant une interface "spring marker" ou une classe finale définie dans ce package uniquement dans le but de scanner les packages.
Prancer
17

Indiquez le nom de votre package séparément, il nécessite un String[]pour les noms de package.

Au lieu de cela:

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

Utilisez ceci:

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

Une autre façon de faire est d'utiliser le basePackageschamp; qui est un champ dans l'annotation ComponentScan.

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

Si vous regardez dans l'annotation ComponentScan .class à partir du fichier jar, vous verrez un champ basePackages qui prend dans un tableau de chaînes

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

Ou vous pouvez mentionner les classes explicitement. Qui prend dans un tableau de classes

Class<?>[]  basePackageClasses
shashwatZing
la source
4

Vous utilisez ComponentScan pour analyser plusieurs packages en utilisant

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

ksw
la source
1

assurez-vous d'avoir ajouté cette dépendance dans votre pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Amirtha Krishnan
la source
Merci après avoir passé près d'une demi-heure, c'était la dépendance manquante
DvixExtract
1

J'utilise:

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

Vous pouvez également utiliser l'annotation @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
la source
4
S'il vous plaît envisager d'ajouter une explication à votre réponse
yeya