`` En continuité de l’article sur les Beans, nous allons faire un focus sur les @Conditional !
Pour bien commencer, une définition s’impose ! Qu’est-ce qu’un @Conditional ?
C’est une annotation qui permet de créer des conditions de création d’un Bean. Elle peut être mise sur une classe ou une méthode.
Dans cet article, nous allons voir plusieurs types de @Conditional, et les illustrer via des exemples.
Avant de commencer, pour tous les exemples, nous allons utiliser un service qui sera une interface, que l’on va ensuite implémenter de différentes manières en utilisant des @Conditional.
Cette interface sera injectée dans un controller RESTREST (REpresentational State Transfer) est un style d'architecture logicielle qui fonctionne sous un certain nombre de contraintes. grâce à @Autowired.
Controller REST :
@RestController
@RequestMapping("/api")
public class SimpleResource {
@Autowired
TravaillerService mTravaillerService;
@GetMapping("/work")
String work() {
return mTravaillerService.doWork();
}
}
Interface du service :
public interface TravaillerService {
String doWork();
}
@ConditionalOnProperty vérifie si la propriété du context contient une valeur. Par défaut, la propriété demandée doit être présente, et différente de false.
On peut utiliser havingValue() et matchIfMissing() afin de personnaliser ce comportement.
Le chemin de la propriété est défini grâce à prefix() et value().
havingValue() est utilisé pour préciser la valeur que la propriété doit avoir.
Si la propriété n’existe pas dans le context, matchIfMissing() est utilisé.
Implémentation 1 :
@Service
@ConditionalOnProperty(prefix = "entreprise", name = "domaine.titre", havingValue = "developpeur")
public class DevelopperTravaillerServiceImpl implements TravaillerService {
@Override
public String doWork() {
return "Coder";
}
}
Implémentation 2 :
@Service
@ConditionalOnProperty(name = "entreprise.domaine.titre", havingValue = "graphiste")
public class GraphisteTravaillerServicerImpl implements TravaillerService {
@Override
public String doWork() {
return "Dessiner";
}
}
Fichier de properties :
entreprise.domaine.titre=graphiste
En lançant avec le fichier de properties ci-dessus, l’implémentation 2 va donc être injectée, et la réponse à /api/work sera « Dessiner ».
Match uniquement quand aucun autre Bean spécifié n’a été instancié.
La condition peut seulement vérifier les Beans qui ont été traités jusqu’à maintenant. Si un autre Bean est susceptible d’être créé par une autre configuration, attention donc à l’utiliser en dernier.
Implémentation 3 :
@Service
@ConditionalOnMissingBean(value = {DevelopperTravaillerServiceImpl.class, GraphisteTravaillerServicerImpl.class})
public class DefautTravaillerServiceImpl implements TravaillerService {
@Override
public String doWork() {
return "Dormir";
}
}
Fichier de properties :
entreprise.domaine.titre=pianiste
En lançant avec le fichier de properties ci-dessus, aucun des 2 Beans Developper et Graphiste ne seront instanciés.
L’implémentation 3 va donc être injectée, et la réponse à /api/work sera «Dormir ».
Comportement inverse de @ConditionalOnMissingBean, match uniquement quand le ou tous les Beans sont présents.
Utilisé avec une ou des org.springframework.context.annotation.Conditions. Toutes les conditions doivent être bonnes pour que le @Conditional match.
Condition :
public class ArchitecteCondition implements Condition {
@Override
public boolean matches(ConditionContext pConditionContext, AnnotatedTypeMetadata pAnnotatedTypeMetadata) {
return "architecte".equals(pConditionContext.getEnvironment().getProperty("entreprise.domaine.titre"));
}
}
Implémentation 4 :
@Service
@Conditional(value = ArchitecteCondition.class)
public class ArchitecteTravaillerServiceImpl implements TravaillerService {
@Override
public String doWork() {
return "Architecturer";
}
}
Fichier de properties :
entreprise.domaine.titre=architecte
Avec la configuration ci-dessus, nous aurons donc « Architecturer » lors de l’appel à l’APIUne API est un programme permettant à deux applications distinctes de communiquer entre elles et d’échanger des données..
Il existe d’autres types de @Conditional, mais ceux-ci devraient être ceux qui vous serviront le plus.
A savoir qu’ils peuvent également être utilisés sur des méthodes, ce qui peut permettre de faire des configurations plus poussées.
Un exemple ci-dessous permettant de gérer simplement le service TravaillerService en fonction de 2 propriétés, et seulement 2 classes.
Configuration 1 :
/**
* Configuration lorsque multitache est à false dans application.properties
*/
@Configuration
@ConditionalOnProperty(name = "entreprise.domaine.multitache", havingValue = "false")
public class TravaillerServiceConfiguration {
@Bean(name = "doWork")
@Conditional(value = ArchitecteCondition.class)
public TravaillerService doWorkArchitecte() {
return () -> "Architecturer";
}
@Bean(name = "doWork")
@ConditionalOnProperty(name = "entreprise.domaine.titre", havingValue = "graphiste")
public TravaillerService doWorkGraphist() {
return () -> "Dessiner";
}
@Bean(name = "doWork")
@ConditionalOnProperty(prefix = "entreprise", name = "domaine.titre", havingValue = "developpeur")
public TravaillerService doWorkDevelopper() {
return () -> "Coder";
}
}
Configuration 2 :
/**
* Configuration lorsque multitache est à true dans application.properties
*/
@Configuration
@ConditionalOnProperty(name = "entreprise.domaine.multitache", havingValue = "true")
public class TravaillerMultitacheServiceConfiguration {
@Bean(name = "doWork")
@Conditional(value = ArchitecteCondition.class)
public TravaillerService doWorkArchitecte() {
return () -> "Architecturer, et plein d’autres choses";
}
@Bean(name = "doWork")
@ConditionalOnProperty(name = "entreprise.domaine.titre", havingValue = "graphiste")
public TravaillerService doWorkGraphist() {
return () -> "Dessiner, et plein d’autres choses";
}
@Bean(name = "doWork")
@ConditionalOnProperty(prefix = "entreprise", name = "domaine.titre", havingValue = "developpeur")
public TravaillerService doWorkDevelopper() {
return () -> "Coder, et plein d’autres choses";
}
}
Avec ces 2 classes, nous avons donc 8 Beans avec 8 possibilités de @Conditional : 4 lorsque entreprise.domaine.multitache est à true et 4 lorsqu’il est à false.
Fichier de properties :
entreprise.domaine.titre=architecte
entreprise.domaine.multitache=true
Avec le fichier de properties ci-dessus, nous aurons donc « Architecturer, et plein d’autres choses » en réponse à l’API.
Les @Conditional sont très puissants, et ne demandent qu’à être utilisés correctement, afin de faire des applications hautement paramétrables.
Le lexique du bug et du débug : tous les termes et méthodes pour comprendre comment débugguer efficacement une application ou un programme informatique.
Découvrez pas à pas comment faire votre premier serveur web en Rust avec Rocket et Diesel !
Avec Jboss AS 7 il est difficile de trouver un plugin simple permettant à la fois de remonter les informations de monitoring et des graphiques de performances.