Aller au contenu

Spring Boot - créer votre propre starter

Découvrez comment créer votre propre starter Spring Boot, centraliser la configuration et fournir des services réutilisables. À travers un exemple concret, apprenez à rendre vos applications plus cohérentes, modulaires et faciles à maintenir.

à vos marque, prêt, starter !

Depuis son apparition en 2014, Spring Boot a changé la manière de développer des applications Java. Là où Spring Framework exigeait souvent de longues configurations XML ou Java, Spring Boot a proposé une approche « convention over configuration » : des choix par défaut sensés, et la possibilité d’overrider facilement via des propriétés.

Les starters Spring Boot participent à cette philosophie. Ils regroupent des dépendances et des auto-configurations prêtes à l’emploi, pour permettre aux développeurs de se concentrer sur la logique métier plutôt que sur l’infrastructure.

Dans un projet d’entreprise ou dans un écosystème plus large, écrire ses propres starters permet d’encapsuler des pratiques communes : sécurité, journalisation, observabilité, connexion aux bases de données internes, etc.
Cet article montre pourquoi et comment écrire un starter personnalisé, en prenant comme exemple un starter minimaliste

Présentation des starters Spring Boot

Un starter Spring Boot, au sens large, est une dépendance qui fournit :

  1. Des dépendances Maven : par exemple spring-boot-starter-web inclut automatiquement Spring MVC, Tomcat, Jackson, etc.
  2. Une auto-configuration : un mécanisme qui crée et configure automatiquement des beans dans le context Spring si certaines conditions sont réunies.

Le mécanisme repose sur :

  • l’annotation @Configuration (ou @AutoConfiguration depuis Spring Boot 3),
  • les conditions comme @ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty qui définissent quand l’auto-configuration s’active,
  • un fichier de déclaration META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

⚖️ Avantages et inconvénients de créer ses propres starters

➕ Avantages

  • Réduction de la duplication : Au lieu de recopier des dizaines de lignes de configuration dans chaque projet, on les centralise dans un starter.
  • Facilité d’onboarding : Un nouveau projet ou un nouvel arrivant dans l’équipe n’a qu’à ajouter une dépendance Maven pour obtenir une configuration cohérente.
  • Uniformisation :Tous les projets utilisent la même version des dépendances, la même configuration par défaut, et appliquent les mêmes standards.
  • Personnalisation contrôlée : Les starters exposent des @ConfigurationProperties : l’utilisateur final peut personnaliser les valeurs dans application.properties ou application.yml.
  • Productivité accrue : Moins de temps perdu à configurer, plus de temps pour coder le métier.

➖ Inconvénients

  • Risque de sur-configuration : Un starter trop intrusif peut imposer des choix difficiles à contrecarrer. Il faut toujours laisser la possibilité de désactiver ou de remplacer les beans.
  • Maintenance : Un starter doit être maintenu : mises à jour des dépendances, compatibilité avec les nouvelles versions de Spring Boot, corrections de sécurité.
  • Compatibilité multi-version : Entre Spring Boot 2 et 3, les mécanismes de déclaration d’auto-configuration ont changé (spring.factories vs AutoConfiguration.imports). Il faut choisir sa cible ou supporter les deux.
  • Complexité de test : Bien que Spring propose des outils (ApplicationContextRunner), écrire des starters testés et fiables exige une certaine discipline.

Exemple : un starter minimaliste

Pour illustrer, nous utilisons greeting-starter, un starter très simple qui fournit un service d’accueil configurable.

Classe d’auto-configuration : GreetingAutoConfiguration

@Configuration
@ConditionalOnClass(GreetingService.class)
@EnableConfigurationProperties(GreetingProperties.class)
public class GreetingAutoConfiguration {

    private final GreetingProperties properties;

    public GreetingAutoConfiguration(GreetingProperties properties) {
        this.properties = properties;
    }

    @Bean
    public GreetingService greetingService() {
        return new GreetingService(properties);
    }
}

Rôle et utilité :

  • @Configuration : indique que cette classe contient des définitions de beans Spring.
  • @ConditionalOnClass(GreetingService.class) : l’auto-configuration ne sera activée que si la classe GreetingService est présente sur le classpath. Cela permet d’éviter les erreurs si la dépendance est absente.
  • @EnableConfigurationProperties(GreetingProperties.class) : indique à Spring Boot de lier automatiquement les propriétés définies dans GreetingProperties aux valeurs de application.properties ou application.yml.
  • greetingService() : méthode annotée @Bean qui crée le bean GreetingService. C’est le service que l’utilisateur final pourra injecter directement dans ses composants.

Classe de propriétés : GreetingProperties

@ConfigurationProperties(prefix = "greeting")
public class GreetingProperties {

    private String message = "Hello, World!";

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Rôle et utilité :

  • Contient les paramètres configurables de notre starter. Ici, uniquement le message de salutation.
  • prefix = "greeting" : toutes les propriétés commençant par greeting. dans application.properties seront mappées automatiquement sur les champs de cette classe.
  • Valeur par défaut (Hello, World!) : permet d’avoir un comportement fonctionnel même si l’utilisateur n’écrit pas de configuration personnalisée.

Service fourni : GreetingService

public class GreetingService {

    private final GreetingProperties properties;

    public GreetingService(GreetingProperties properties) {
        this.properties = properties;
    }

    public String greet() {
        return properties.getMessage();
    }
}

Rôle et utilité :

  • C’est le cœur fonctionnel du starter : il expose une méthode greet() qui retourne le message configuré.
  • Injecte GreetingProperties pour récupérer la valeur du message configuré par l’utilisateur.
  • Peut être facilement injecté dans n’importe quel composant Spring grâce à l’auto-configuration.

Déclaration de l’auto-configuration

Dans vos resource ajoutez un fichier META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

qui contiendra

xxxxx.yyyyyy.configuration.GreetingAutoConfiguration

Rôle et utilité :

  • Indique à Spring Boot quelles classes d’auto-configuration doivent être chargées automatiquement lors du démarrage.
  • Depuis Spring Boot 3, ce fichier remplace le mécanisme historique spring.factories.
  • Chaque ligne correspond à une classe d’auto-configuration qui sera scannée et instanciée si les conditions sont remplies.

Utilisation dans l’application cliente

Dans l'application ou vous souhaitez utiliser votre starter, vous n'avez qu'à importer la dépendance vers ce dernier dans votre fichier pom.xml :

<dependency>
    <groupId>fr.eletutour</groupId>
    <artifactId>greeting-starter</artifactId>
    <version>${project.version}</version>
</dependency>

Et ajouter la properties à surcharger dans votre fichier application.properties :

greeting.message=Hello from custom starter!

Il ne vous reste plus maintenant qu'à utiliser le service configuré dans le starter.

@SpringBootApplication
public class GreetingApplication implements CommandLineRunner {

    private static final Logger LOG = LoggerFactory.getLogger(GreetingApplication.class);
    private final GreetingService greetingService;

    public GreetingApplication(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    public static void main(String[] args) {
        SpringApplication.run(GreetingApplication.class, args);
    }

    @Override
    public void run(String... args) {
        LOG.info(greetingService.greet());
    }
}
  • GreetingService est injecté automatiquement grâce à l’auto-configuration.
  • CommandLineRunner permet de vérifier immédiatement le fonctionnement du starter en affichant le message configuré au démarrage.
  • L’utilisateur final n’a aucune configuration supplémentaire à écrire : le starter s’occupe de tout.

Au démarrage de l'application nous aurons une ligne de log affichant le message configuré :

2025-09-25T08:49:19.081+02:00  INFO 81860 --- [           main] fr.eletutour.GreetingApplication         : Hello from custom starter!

Et la suite ? Vers un starter plus complet

L’exemple greeting-starter que nous avons vu est volontairement minimaliste : il expose un seul service et une seule propriété. Mais les concepts que nous avons appliqués peuvent être étendus pour créer des starters beaucoup plus riches et réutilisables dans des projets professionnels. Voici quelques pistes pour aller plus loin :

Multiples services et beans configurables

Plutôt que de se limiter à un simple GreetingService, un starter peut fournir plusieurs services liés, par exemple :

  • un service de traduction (TranslationService) qui adapte les messages à la langue de l’utilisateur,
  • un service de logging ou de traçabilité des messages (MessageAuditService),
  • un service de formatage configurable (MessageFormatter) qui applique des styles ou des templates.

Chacun de ces services pourrait être activé ou désactivé selon des propriétés spécifiques, et être conditionné par @ConditionalOnMissingBean pour permettre aux applications clientes de les surcharger.

Propriétés hiérarchiques et dynamiques

Au lieu d’une seule propriété message, on pourrait imaginer :

greeting.default-message=Hello
greeting.farewell-message=Goodbye
greeting.style=uppercase
greeting.enabled=true

Ces propriétés pourraient être liées à une classe GreetingProperties enrichie, avec des comportements différents selon la configuration. Cela permet de gérer plusieurs cas d’usage depuis un même starter.

Prise en charge de profils et d’environnements

Un starter peut détecter le profil Spring actif (dev, prod, test) et adapter ses beans ou valeurs par défaut en conséquence :

  • un message différent en développement pour le debugging,
  • un message en production plus formel,
  • des fonctionnalités désactivées dans les tests pour alléger le contexte Spring.

Intégration avec d’autres frameworks ou librairies

On pourrait imaginer que notre starter interagisse avec :

  • Spring Security pour limiter qui peut utiliser certaines fonctionnalités du service,
  • Spring Web pour exposer une API REST de messages configurables,
  • un système de cache ou de base de données pour stocker des messages personnalisés.

Conclusion

Écrire son propre starter Spring Boot, c’est investir dans la simplicité et la cohérence. Comme nous l’avons vu avec greeting-starter, quelques classes suffisent pour exposer une configuration réutilisable et personnalisable.

Dans un contexte d’équipe ou d’organisation, les starters deviennent de véritables briques de standardisation, réduisant la dette technique et favorisant la productivité. Leur principal défi est la maintenance : veiller à leur compatibilité, documenter leurs propriétés, et les tester régulièrement.

En définitive, les starters ne doivent pas être vus comme une fin en soi, mais comme un outil pour encapsuler ce qui doit être commun, sans priver les projets de leur liberté.
La règle d’or : proposer des valeurs par défaut utiles, mais toujours faciles à override.


Tout le code relatif à cet article est trouvable ici :

GitHub - ErwanLT/springboot-demo: Demo project for spring-boot possibility
Demo project for spring-boot possibility. Contribute to ErwanLT/springboot-demo development by creating an account on GitHub.

Dernier