Analyse des composants Spring

1. Vue d'ensemble

Dans ce didacticiel, nous aborderons l'analyse des composants dans Spring. Lorsque vous travaillez avec Spring, nous pouvons annoter nos classes afin de les transformer en haricots Spring. Mais, en plus de cela, nous pouvons dire à Spring où rechercher ces classes annotées car toutes ne doivent pas devenir des beans dans cette exécution particulière.

Bien sûr, il existe des valeurs par défaut pour l'analyse des composants, mais nous pouvons également personnaliser les packages pour la recherche.

Tout d'abord, regardons les paramètres par défaut.

2. @ComponentScan sans arguments

2.1. Utilisation de @ComponentScan dans une application Spring

Avec Spring, nous utilisons l' annotation @ComponentScan avec l' annotation @Configuration pour spécifier les packages que nous voulons analyser . @ComponentScan sans arguments indique à Spring d'analyser le package actuel et tous ses sous-packages.

Disons que nous avons la @Configuration suivante dans le package com.baeldung.componentscan.springapp :

@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); } } }

De plus, disons que nous avons les composants Cat et Dog dans le package com.baeldung.componentscan.springapp.animals :

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

Et enfin, nous avons le composant Rose dans le package com.baeldung.componentscan.springapp.flowers :

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

La sortie de la méthode main () contiendra tous les beans du package com.baeldung.componentscan.springapp et de ses sous-packages:

springComponentScanApp cat dog rose exampleBean

Notez que la classe d'application principale est également un bean car elle est annotée avec @Configuration, qui est un @Component .

Notez également que la classe d'application principale et la classe de configuration ne sont pas nécessairement les mêmes. S'ils sont différents, peu importe où placer la classe d'application principale. Seul l'emplacement de la classe de configuration compte, car l'analyse des composants démarre par défaut à partir de son package .

Enfin, notez que dans notre exemple @ComponentScan équivaut à:

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

où l' argument basePackages est un package ou un tableau de packages à analyser.

2.2. Utilisation de @ComponentScan dans une application Spring Boot

L'astuce avec Spring Boot est que beaucoup de choses se produisent implicitement. Nous utilisons l' annotation @SpringBootApplication , mais ce n'est qu'une combinaison de trois annotations:

@Configuration @EnableAutoConfiguration @ComponentScan

Créons une structure similaire dans le package com.baeldung.componentscan.springbootapp . Cette fois, l'application principale sera:

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)); } } }

Tous les autres packages et classes restent les mêmes, nous les copierons simplement dans le package com.baeldung.componentscan.springbootapp situé à proximité .

Spring Boot analyse les packages de la même manière que notre exemple précédent. Vérifions la sortie:

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

La raison pour laquelle nous vérifions simplement l'existence des beans dans notre deuxième exemple (par opposition à l'impression de tous les beans), est que la sortie serait trop grande.

Cela est dû à l' annotation implicite @EnableAutoConfiguration qui permet à Spring Boot de créer automatiquement de nombreux beans, en s'appuyant sur les dépendances du fichier pom.xml .

3. @ComponentScan avec des arguments

Personnalisons maintenant les chemins de numérisation. Par exemple, disons que nous voulons exclure le haricot rose .

3.1. @ComponentScan pour des packages spécifiques

Nous pouvons le faire de plusieurs façons. Tout d'abord, nous pouvons changer le package de base:

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

Maintenant, la sortie sera:

springComponentScanApp cat dog exampleBean

Voyons ce qu'il y a derrière cela:

  • springComponentScanApp est créé car il s'agit d'une configuration transmise en tant qu'argument à AnnotationConfigApplicationContext
  • exampleBean est un bean configuré dans la configuration
  • chat et chien sont dans le package com.baeldung.componentscan.springapp.animals spécifié

Toutes les personnalisations énumérées ci-dessus sont également applicables dans Spring Boot. Nous pouvons utiliser @ComponentScan avec @SpringBootApplication et le résultat sera le même:

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

3.2. @ComponentScan avec exclusions

Une autre façon consiste à utiliser un filtre, en spécifiant le modèle pour les classes à exclure:

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

Nous pouvons également choisir un type de filtre différent, car l'annotation prend en charge plusieurs options flexibles pour filtrer les classes numérisées :

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

4. Le package par défaut

Nous devons éviter de mettre la classe @Configuration dans le package par défaut (c'est-à-dire en ne spécifiant pas du tout le package). Dans ce cas, Spring analyse toutes les classes de tous les fichiers JAR d'un chemin de classe. Cela provoque des erreurs et l'application ne démarre probablement pas.

5. Conclusion

Dans cet article, nous avons appris quels packages Spring scanne par défaut et comment personnaliser ces chemins.

Comme d'habitude, le code complet est disponible sur sur GitHub.