Décryptage de l'annotation SpringBootApplication

Décryptage de l'annotation SpringBootApplication

Annotation SpringBootApplication

L'annotation SpringBootApplication est une annotation composée qui regroupe trois annotations essentielles :

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

Cette annotation unique combine donc les fonctionnalités de ces trois annotations distinctes.

Fonction de l'annotation @SpringBootConfiguration

On peut voir que l'annotation SpringBootConfiguration hérite de l'annotation Configuraton. Son rôle est donc clair : traiter la classe principale de l'application comme une classe de configuration. Cela nous permet d'enregistrer des beans dans le conteneur IOC directement dans la classe principale en utilisant l'annotation @Bean.

Annotation @EnableAutoConfiguration

@EnableAutoConfiguration est la clé de la configuration automatique dans Spring Boot. Analysons d'abord @Import(AutoConfigurationImportSelector.class). L'annotation @Import permet d'enregistrer des objets dans le conteneur IOC, d'importer indirectement des objets via des implémentations d'ImportSelector, ou d'importer des BeanDefinition.

@Import(AutoConfigurationImportSelector.class) enregistre en réalité un objet AutoConfigurationImportSelector dans le conteneur IOC. La méthode selectImports de cet objet retourne un tableau de String[] dont les éléments sont ajoutés au conteneur IOC.

Examinons ce que fait la méthode selectImports :


// selectImports est une méthode définie dans l'interface ImportSelector
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    List<string> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    configurations = removeDuplicates(configurations);
    Set<string> exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

protected List<string> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // Mécanisme SPI Spring pour charger les classes d'autoconfiguration depuis le fichier spring.factories
    List<string> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
            getBeanClassLoader());
    Assert.notEmpty(configurations, "Aucune classe de configuration automatique trouvée dans META-INF/spring.factories. Si vous "
            + "utilisez un packaging personnalisé, assurez-vous que ce fichier est correct.");
    return configurations;
}

protected Class> getSpringFactoriesLoaderFactoryClass() {
    return EnableAutoConfiguration.class;
}
</string></string></string></string>

Examinons maintenant le contenu de ce fichier spring.factories :


# Configuration automatique
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\

On peut placer un point d'arrêt pour vérifier ce processus.

Rôle de l'annotation @AutoConfigurationPackage

Le rôle principal de cette annotation est de marquer et d'enregistrer le package contenant la classe de démarrage de Spring Boot comme « package de configuration automatique », permettant à Spring de scanner les composants personnalisés (comme @Controller, @Service, @Repository, etc.) dans ce package et ses sous-packages.


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage

Cette annotation utilise également l'annotation @Import. L'import est donc une mécanisme très important. AutoConfigurationPackages.Registrar est une implémentation d'ImportBeanDefinitionRegistrar qui permet de définir des informations BeanDefinition dans le conteneur IOC.

On peut voir que le package importé est exactement le package contenant la classe de démarrage, ce qui explique pourquoi la classe de démarrrage par défaut scanne tous les composants dans son package et ses sous-packages.

Annotation @ComponentScan

Cette annotation est bien connue et ne nécessite pas une explication détaillée ici.

Conclusion

L'annotation SpringBootApplication sur la classe principale de démarrage est en réalité une combinaison de :

  • @SpringBootConfiguration - équivalent à @Configuration, marquant la classe de démarrage comme classe de configuration.
  • @EnableAutoConfiguration - configurant automatiquement les composants que nous souhaitons étendre et définissant les basePackage.
  • @ComponentScan - balayant tous les composants dans le package de la classe de démarrage et ses sous-packages.

Étiquettes: Spring Boot Annotation configuration automatique IOC Java

Publié le 2 juin à 20h06