
Gestion des profils (`spring.profiles.active`, `@Profile`)
Apprenez à utiliser les profils Spring Boot pour adapter votre configuration à différents environnements (dev, test, prod) via spring.profiles.active et @Profile.
Pourquoi des profils ? Adapter l'application aux environnements
Une application logicielle évolue rarement dans un seul et unique environnement. Typiquement, elle passe par plusieurs étapes : développement local sur la machine du développeur, tests d'intégration sur une plateforme dédiée, pré-production (staging) pour les validations finales, et enfin production pour les utilisateurs finaux. Chacun de ces environnements peut avoir des besoins de configuration très différents :
- La base de données de développement n'est pas celle de production.
- Les clés d'API pour les services externes peuvent différer.
- Le niveau de journalisation (logging) peut être plus détaillé en développement qu'en production.
- Certains composants (comme des simulateurs ou mocks) ne doivent être actifs qu'en test ou en développement.
Gérer ces variations de configuration de manière ad hoc peut vite devenir un cauchemar. C'est là qu'intervient le concept de profils Spring. Les profils permettent de regrouper des définitions de beans et des configurations de propriétés spécifiques à un environnement ou à un cas d'usage particulier. Ils offrent un moyen standardisé et puissant de segmenter la configuration de votre application et de n'activer que les parties pertinentes en fonction du contexte d'exécution.
Activer les profils : la propriété `spring.profiles.active`
La manière la plus courante de spécifier quels profils doivent être actifs pour une exécution donnée de votre application Spring Boot est d'utiliser la propriété spring.profiles.active. Cette propriété peut être définie dans n'importe quelle source de configuration reconnue par Spring Boot (fichier application.properties/.yml, variables d'environnement, arguments de ligne de commande, etc.).
Vous pouvez activer un ou plusieurs profils en les listant, séparés par une virgule (sans espace autour de la virgule si définie dans un fichier .properties).
Exemple dans application.properties :
# Activer le profil 'dev'
spring.profiles.active=devExemple dans application.yml :
spring:
profiles:
active: dev # Activer le profil 'dev'
# Ou pour plusieurs profils :
# spring:
# profiles:
# active: dev,h2 # Activer 'dev' ET 'h2'Il est souvent préférable de ne pas définir spring.profiles.active directement dans le fichier application.properties ou application.yml principal (celui inclus dans le JAR/WAR), car ce fichier est commun à tous les environnements. Il est plus judicieux de définir le profil actif via des sources externes qui ont une priorité plus élevée, garantissant ainsi que chaque environnement utilise sa propre configuration :
- Argument de ligne de commande :
java -jar mon-app.jar --spring.profiles.active=prod - Variable d'environnement système :
export SPRING_PROFILES_ACTIVE=prod(ouset SPRING_PROFILES_ACTIVE=prodsous Windows) puisjava -jar mon-app.jar - Propriété système JVM :
java -Dspring.profiles.active=prod -jar mon-app.jar
L'utilisation de variables d'environnement ou d'arguments de ligne de commande est la pratique la plus répandue pour définir le profil en production ou dans les pipelines CI/CD.
Spring Boot propose aussi la propriété spring.profiles.include qui permet à un profil d'en inclure automatiquement d'autres, mais spring.profiles.active reste la méthode principale pour l'activation initiale.
Configuration spécifique aux profils : fichiers `application-{profile}.properties`/`yml`
Une fois qu'un ou plusieurs profils sont actifs, Spring Boot charge automatiquement des fichiers de configuration spécifiques à ces profils, en plus du fichier principal application.properties ou application.yml. La convention de nommage est simple : application-{nomDuProfil}.properties ou application-{nomDuProfil}.yml.
Par exemple, si le profil `prod` est actif, Spring Boot cherchera et chargera (s'il existe) le fichier application-prod.properties (ou .yml). Les propriétés définies dans ce fichier spécifique au profil ont priorité sur celles définies dans le fichier application.properties (ou .yml) principal. Cela permet de surcharger les valeurs par défaut pour un environnement spécifique.
Exemple de structure de fichiers dans src/main/resources :
src/
└── main/
└── resources/
├── application.properties (Configuration commune/par défaut)
├── application-dev.properties (Configuration spécifique pour le profil 'dev')
└── application-prod.properties (Configuration spécifique pour le profil 'prod')Contenu de application.properties :
app.greeting=Bonjour (défaut)
server.port=8080Contenu de application-dev.properties :
app.greeting=Bonjour Développeur !
spring.datasource.url=jdbc:h2:mem:testdb # Base H2 en mémoire pour devContenu de application-prod.properties :
server.port=80 # Surcharge le port par défaut pour prod
spring.datasource.url=jdbc:mysql://prod-db.example.com/maindb # Base MySQL de prod
# app.greeting n'est pas redéfini, utilise la valeur par défaut "Bonjour (défaut)"Si l'application est lancée avec --spring.profiles.active=dev, le message sera "Bonjour Développeur !" et la base de données H2 sera utilisée. Si lancée avec --spring.profiles.active=prod, le port sera 80, la base MySQL sera utilisée, et le message restera "Bonjour (défaut)".
Beans conditionnels : l'annotation `@Profile`
Au-delà de la configuration des propriétés, les profils permettent également de contrôler l'enregistrement des beans dans le conteneur Spring. L'annotation @Profile peut être utilisée pour indiquer qu'un composant (par exemple, une classe annotée avec @Component, @Service, @Repository, ou @Configuration) ou une méthode de fabrique (annotée avec @Bean) ne doit être chargé que si un ou plusieurs profils spécifiques sont actifs.
Exemple : Un service de notification différent pour la production et le développement/test
public interface NotificationService {
void send(String message);
}
@Service
@Profile("prod") // Actif uniquement si le profil 'prod' est actif
public class EmailNotificationService implements NotificationService {
@Override
public void send(String message) {
System.out.println("Envoi d'un VRAI email (PROD): " + message);
// Logique d'envoi d'email réelle...
}
}
@Service
@Profile("!prod") // Actif si le profil 'prod' n'est PAS actif (dev, test, etc.)
// Ou @Profile({"dev", "test"}) si on veut être plus spécifique
public class LogNotificationService implements NotificationService {
@Override
public void send(String message) {
System.out.println("LOG (Non-PROD): " + message);
// Simule l'envoi en loggant simplement
}
}
// Utilisation
@RestController
public class MyController {
private final NotificationService notificationService;
@Autowired
public MyController(NotificationService notificationService) {
// Spring injectera l'implémentation active selon le profil
this.notificationService = notificationService;
}
@GetMapping("/notify")
public String notify(@RequestParam String msg) {
notificationService.send(msg);
return "Notification envoyée via " + notificationService.getClass().getSimpleName();
}
}Dans cet exemple, si l'application est lancée avec le profil `prod`, c'est `EmailNotificationService` qui sera créé et injecté. Si elle est lancée sans le profil `prod` (ou avec `dev` ou `test`), c'est `LogNotificationService` qui sera utilisé. L'annotation @Profile peut aussi être placée sur des classes @Configuration ou des méthodes @Bean pour conditionner la création de beans définis programmatiquement.
Expressions de profils et profil `default`
L'annotation @Profile accepte des expressions plus complexes pour des conditions plus fines :
- OU :
@Profile({"dev", "test"})- Actif si le profil `dev` OU `test` est actif. - ET :
@Profile("cloud & mysql")- Actif si le profil `cloud` ET `mysql` sont actifs. (Note:&doit être échappé en&dans le code Java si utilisé directement, mais il est plus sûr d'utiliser `&` dans un contexte Spring). - NON :
@Profile("!prod")- Actif si le profil `prod` n'est PAS actif.
Ces opérateurs peuvent être combinés avec des parenthèses pour des logiques plus élaborées, par exemple @Profile("(dev | test) & h2").
Enfin, il existe un profil spécial nommé default. Ce profil est actif par défaut si aucun autre profil n'est explicitement activé via spring.profiles.active. Vous pouvez utiliser @Profile("default") pour définir des beans ou des configurations qui ne s'appliquent que lorsque l'application est lancée sans profil spécifique. Cependant, il est généralement recommandé de toujours définir explicitement un profil pour chaque environnement afin d'éviter toute ambiguïté.
Conclusion : flexibilité et robustesse pour tous les environnements
La gestion des profils est une fonctionnalité essentielle de Spring Boot pour construire des applications adaptables et robustes. En combinant la propriété spring.profiles.active, les fichiers de configuration spécifiques aux profils (application-{profile}.properties/.yml) et l'annotation @Profile, vous disposez d'un arsenal complet pour :
- Séparer clairement les configurations spécifiques à chaque environnement.
- Activer ou désactiver des composants logiciels en fonction du contexte.
- Simplifier le déploiement et la maintenance en évitant les configurations manuelles complexes à chaque étape.
Maîtriser les profils est donc indispensable pour tout développeur Spring Boot souhaitant livrer des applications professionnelles et facilement gérables dans divers environnements.