
Création de ses propres auto-configurations
Apprenez à étendre la magie de Spring Boot en créant vos propres auto-configurations pour vos bibliothèques et modules réutilisables, en utilisant les annotations conditionnelles et les bonnes pratiques.
Pourquoi créer ses propres auto-configurations ?
La magie de Spring Boot réside en grande partie dans son système d'auto-configuration. En se basant sur les dépendances présentes dans le classpath, les propriétés définies, ou la présence d'autres beans, Spring Boot configure automatiquement une grande partie de l'infrastructure nécessaire (DataSource, EntityManagerFactory, JmsTemplate, etc.), réduisant considérablement le code de configuration boilerplate.
Mais que faire lorsque vous développez vos propres bibliothèques, frameworks internes ou composants réutilisables que vous souhaitez intégrer aussi facilement dans différentes applications Spring Boot ? C'est là qu'intervient la création de vos propres auto-configurations. En définissant une auto-configuration pour votre module, vous permettez aux utilisateurs de simplement ajouter votre dépendance (souvent sous forme de "starter") pour que les beans nécessaires soient automatiquement configurés et prêts à l'emploi, en suivant les mêmes principes de convention plutôt que de configuration.
Créer une auto-configuration pour vos composants partagés offre plusieurs avantages :
- Réduction du Boilerplate : Les utilisateurs de votre module n'ont plus besoin d'écrire de code de configuration répétitif pour l'intégrer.
- Cohérence : Assure que votre module est configuré de manière cohérente et optimale dans toutes les applications qui l'utilisent.
- Découvrabilité : S'intègre naturellement avec les mécanismes de Spring Boot, rendant votre module facile à utiliser.
- Configuration Conditionnelle : Permet d'activer ou de configurer votre module uniquement si certaines conditions sont remplies (présence de classes, de propriétés, etc.).
Mécanismes clés : @Configuration, @ConditionalOn...
Le coeur d'une auto-configuration est une classe annotée avec @Configuration (il est recommandé d'utiliser @Configuration(proxyBeanMethods = false) pour les auto-configurations car elles n'ont généralement pas besoin des appels inter-beans gérés par les proxies CGLIB, améliorant ainsi légèrement les performances au démarrage).
La puissance de l'auto-configuration réside dans sa capacité à être conditionnelle. Spring Boot fournit une panoplie d'annotations, toutes basées sur la méta-annotation @Conditional, qui permettent d'activer une configuration (ou la création d'un bean spécifique) uniquement si certaines conditions sont réunies. Les plus courantes pour l'auto-configuration sont :
@ConditionalOnClass: La configuration est activée seulement si les classes spécifiées sont présentes dans le classpath. Utile pour configurer un bean qui dépend d'une bibliothèque tierce.@ConditionalOnMissingClass: L'inverse de la précédente.@ConditionalOnBean: La configuration (ou le bean) est activée seulement si un bean du type spécifié existe déjà dans le contexte.@ConditionalOnMissingBean: Très important ! La configuration (ou le bean) est activée seulement si un bean du type spécifié N'existe PAS encore. Cela permet aux utilisateurs de votre module de fournir leur propre implémentation/configuration d'un bean, qui prendra alors la priorité sur votre configuration par défaut.@ConditionalOnProperty: Active la configuration en fonction de la présence et/ou de la valeur d'une propriété dans l'environnement Spring (application.properties, variables d'environnement, etc.). Très utile pour rendre votre module configurable via des propriétés (par exemple,mon.module.enabled=true). L'attributmatchIfMissing = trueest souvent utilisé pour activer la configuration par défaut si la propriété n'est pas définie.@ConditionalOnResource: Active la configuration si une ressource spécifique (fichier) est présente dans le classpath.@ConditionalOnWebApplication/@ConditionalOnNotWebApplication: Active la configuration selon que l'application est une application web ou non.
On peut combiner plusieurs annotations conditionnelles sur une même classe @Configuration ou sur une méthode @Bean. De plus, les annotations @AutoConfigureBefore et @AutoConfigureAfter permettent de spécifier un ordre d'exécution relatif par rapport à d'autres classes d'auto-configuration de Spring Boot ou personnalisées, ce qui est parfois nécessaire si votre configuration dépend de beans créés par une autre auto-configuration.
Processus de création : un exemple concret
Imaginons que nous ayons créé un service simple, MonServicePersonnalise, qui a besoin d'un message configurable. Nous voulons l'auto-configurer.
1. Le service et ses propriétés :
D'abord, le service lui-même (qui serait dans votre module principal) :
// Dans votre module principal (ex: mon-service-lib)
public interface MonServicePersonnalise {
String getMessagePersonnalise();
}
public class MonServicePersonnaliseImpl implements MonServicePersonnalise {
private final String message;
public MonServicePersonnaliseImpl(String message) {
this.message = message;
}
@Override
public String getMessagePersonnalise() {
return "Message du service: " + message;
}
}
Ensuite, une classe pour encapsuler les propriétés de configuration (dans le module d'auto-configuration) :
// Dans votre module d'auto-configuration (ex: mon-service-spring-boot-autoconfigure)
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "mon.service")
public class MonServiceProperties {
/**
* Activer ou désactiver le service personnalisé.
*/
private boolean enabled = true; // Par défaut activé
/**
* Le message à afficher par le service.
*/
private String message = "Bonjour par défaut!";
// Getters et Setters...
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
2. La classe d'auto-configuration :
C'est ici que la magie opère. Créez une classe dans votre module d'auto-configuration :
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false) // Bonne pratique pour les auto-configs
@ConditionalOnClass(MonServicePersonnalise.class) // Ne s'active que si la classe principale est là
@EnableConfigurationProperties(MonServiceProperties.class) // Active la liaison des propriétés
@ConditionalOnProperty(prefix = "mon.service", name = "enabled", havingValue = "true", matchIfMissing = true) // Condition sur propriété
public class MonServiceAutoConfiguration {
private final MonServiceProperties properties;
// Injection des propriétés
public MonServiceAutoConfiguration(MonServiceProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean // Important: permet à l'utilisateur de définir son propre bean
public MonServicePersonnalise monServicePersonnalise() {
// Crée le bean en utilisant les propriétés injectées
return new MonServicePersonnaliseImpl(properties.getMessage());
}
}
Cette classe est annotée pour ne s'activer que si MonServicePersonnalise est disponible et si la propriété mon.service.enabled est à `true` (ou absente). Elle active la liaison avec MonServiceProperties et définit un bean MonServicePersonnalise par défaut, mais seulement si l'utilisateur n'en a pas déjà défini un lui-même.
Rendre l'auto-configuration découvrable
Pour que Spring Boot trouve et exécute votre classe MonServiceAutoConfiguration, vous devez la déclarer d'une manière spécifique. Il existe deux méthodes :
Méthode moderne (Spring Boot 2.7+) : Fichier AutoConfiguration.imports (RECOMMANDEE)
C'est la méthode préférée aujourd'hui. Créez le fichier suivant dans votre module d'auto-configuration :
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Dans ce fichier, listez le nom complet de votre classe d'auto-configuration (une par ligne si vous en avez plusieurs) :
com.example.autoconfig.MonServiceAutoConfigurationMéthode historique (Legacy) : Fichier spring.factories
Cette méthode est toujours supportée pour la compatibilité ascendante mais est dépréciée pour déclarer les auto-configurations. Créez le fichier :
src/main/resources/META-INF/spring.factories
Ajoutez la clé org.springframework.boot.autoconfigure.EnableAutoConfiguration et listez votre classe de configuration :
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MonServiceAutoConfigurationEn utilisant l'une de ces méthodes (préférez la première), Spring Boot saura qu'il doit considérer votre classe MonServiceAutoConfiguration lors de son processus d'auto-configuration.
Packaging : intégration dans un starter
Généralement, une auto-configuration est packagée avec la bibliothèque qu'elle configure pour former un starter Spring Boot. Un starter typique contient :
- La bibliothèque principale (ex:
mon-service-lib.jar). - Le module d'auto-configuration (ex:
mon-service-spring-boot-autoconfigure.jar) contenant la classe@Configurationet le fichierMETA-INF/spring/.../AutoConfiguration.imports. - Un module "starter" (ex:
mon-service-spring-boot-starter.jar) qui est souvent vide mais qui déclare des dépendances transitives vers la bibliothèque et le module d'auto-configuration, ainsi que d'autres dépendances optionnelles nécessaires.
L'utilisateur final ajoute simplement la dépendance du starter (mon-service-spring-boot-starter) à son projet, et grâce à l'auto-configuration, les beans nécessaires sont configurés automatiquement. L'utilisateur peut ensuite personnaliser le comportement via les propriétés définies dans MonServiceProperties (ici, mon.service.enabled et mon.service.message).
Bonnes pratiques et tests
- Spécificité des conditions : Utilisez les annotations
@ConditionalOn...les plus spécifiques possible pour éviter d'activer votre configuration de manière inattendue. - Permettre la surcharge : Utilisez systématiquement
@ConditionalOnMissingBeansur vos définitions de beans par défaut pour permettre aux utilisateurs de fournir leurs propres configurations personnalisées. - Configuration externe : Utilisez
@ConfigurationPropertiespour rendre votre module configurable via les mécanismes standards de Spring Boot. Fournissez une propriété `enabled` pour pouvoir désactiver facilement l'auto-configuration. - Ordre : Utilisez
@AutoConfigureBeforeou@AutoConfigureAftersi votre configuration dépend de l'exécution d'une autre auto-configuration (Spring Boot ou la vôtre). - Fichier
.imports: Utilisez le fichierMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsplutôt quespring.factoriespour déclarer vos auto-configurations. - Tests : Testez rigoureusement votre auto-configuration. Utilisez
ApplicationContextRunnerde Spring Boot Test pour créer des contextes d'application légers et vérifier que vos beans sont (ou ne sont pas) créés en fonction de différentes conditions (présence/absence de classes, de propriétés, de beans).
Créer ses propres auto-configurations est une technique avancée mais extrêmement puissante pour intégrer proprement vos propres modules dans l'écosystème Spring Boot, offrant une expérience utilisateur similaire à celle des starters officiels.