Dans le développement de logiciels modernes, les indicateurs de fonctionnalités jouent un rôle crucial dans la gestion des versions de fonctionnalités. En utilisant des indicateurs de fonctionnalités (également appelés bascules de fonctionnalités), les développeurs peuvent activer ou désactiver des fonctionnalités de manière dynamique sans redéployer l'application. Cette approche permet des versions incrémentielles, une expérimentation contrôlée et des déploiements plus fluides, en particulier dans les systèmes complexes et à grande échelle.
Dans ce blog, nous explorerons comment implémenter des indicateurs de fonctionnalités dans une application Spring Boot à l'aide de la programmation orientée aspect (AOP). AOP nous permet de modulariser des préoccupations transversales telles que la journalisation, la sécurité et le basculement de fonctionnalités, en les séparant de la logique métier principale. En tirant parti d'AOP, nous pouvons concevoir une implémentation d'indicateurs de fonctionnalités flexible et réutilisable qui peut s'adapter à diverses exigences.
Nous montrerons comment AOP peut intercepter les appels de méthode, vérifier les indicateurs de fonctionnalités et exécuter conditionnellement des fonctionnalités en fonction de l'état de l'indicateur. Cela rend l'implémentation plus propre, plus maintenable et plus facile à modifier. Il est recommandé de suivre une compréhension de base d'AOP, de Spring Boot et des indicateurs de fonctionnalités.
Vous pouvez trouver le code référencé dans cet article ici : Feature Flags with Spring Boot.
public interface FeatureFlagValidator { boolean validate(Object... args); }
La méthode validate prend en compte un nombre variable d'arguments (Object... args), ce qui donne la flexibilité de transmettre tous les paramètres nécessaires à la logique de validation. La méthode retournera true si la fonctionnalité doit être activée, ou false si elle doit rester désactivée. Cette conception permet une logique de validation des indicateurs de fonctionnalité réutilisable et facilement configurable.
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface FeatureFlag { Class<? extends FeatureFlagValidator>[] validators(); }
Cette annotation accepte un tableau de classes FeatureFlagValidator, permettant une logique configurable pour déterminer si une fonctionnalité doit être activée ou désactivée.
@Aspect @Component public class FeatureFlagAspect { @Autowired private ApplicationContext applicationContext; @Around(value = "@annotation(featureFlag)", argNames = "featureFlag") public Object checkFeatureFlag(ProceedingJoinPoint joinPoint, FeatureFlag featureFlag) throws Throwable { Object[] args = joinPoint.getArgs(); for (Class<? extends FeatureFlagValidator> validatorClass : featureFlag.validators()) { FeatureFlagValidator validator = applicationContext.getBean(validatorClass); if (!validator.validate(args)) { throw new RuntimeException(ErrorConstants.FEATURE_NOT_ENABLED.getMessage()); } } return joinPoint.proceed(); } }
Cette classe comprend une méthode qui
public interface FeatureFlagValidator { boolean validate(Object... args); }
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface FeatureFlag { Class<? extends FeatureFlagValidator>[] validators(); }
@Aspect @Component public class FeatureFlagAspect { @Autowired private ApplicationContext applicationContext; @Around(value = "@annotation(featureFlag)", argNames = "featureFlag") public Object checkFeatureFlag(ProceedingJoinPoint joinPoint, FeatureFlag featureFlag) throws Throwable { Object[] args = joinPoint.getArgs(); for (Class<? extends FeatureFlagValidator> validatorClass : featureFlag.validators()) { FeatureFlagValidator validator = applicationContext.getBean(validatorClass); if (!validator.validate(args)) { throw new RuntimeException(ErrorConstants.FEATURE_NOT_ENABLED.getMessage()); } } return joinPoint.proceed(); } }
@Component @RequiredArgsConstructor public class FeatureAFeatureFlag implements FeatureFlagValidator { private final FeatureFlagConfigs featureFlagConfigs; private final Logger logger = LoggerFactory.getLogger(FeatureAFeatureFlag.class); @Override public boolean validate(Object... args) { boolean result = featureFlagConfigs.getFeatureAEnabled(); if (!result) { logger.error("Feature A is not enabled!"); } return result; } }
Depuis, nous avons annoté notre méthode avec l'annotation FeatureFlag et utilisé la classe FeatureAFeatureFlag, donc avant d'exécuter la méthode featureA, FeatureAFeatureFlag sera exécuté et il vérifiera si la fonctionnalité est activée ou non.
Notez ici que le champ des validateurs est un tableau dans l'annotation FeatureFlag, nous pouvons donc lui transmettre plusieurs validateurs.
Pour implémenter l'indicateur de fonctionnalité pour la fonctionnalité B, nous devrons mettre à jour les fichiers FeatureFlagConfigs et application.properties en conséquence.
public interface FeatureFlagValidator { boolean validate(Object... args); }
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface FeatureFlag { Class<? extends FeatureFlagValidator>[] validators(); }
@Aspect @Component public class FeatureFlagAspect { @Autowired private ApplicationContext applicationContext; @Around(value = "@annotation(featureFlag)", argNames = "featureFlag") public Object checkFeatureFlag(ProceedingJoinPoint joinPoint, FeatureFlag featureFlag) throws Throwable { Object[] args = joinPoint.getArgs(); for (Class<? extends FeatureFlagValidator> validatorClass : featureFlag.validators()) { FeatureFlagValidator validator = applicationContext.getBean(validatorClass); if (!validator.validate(args)) { throw new RuntimeException(ErrorConstants.FEATURE_NOT_ENABLED.getMessage()); } } return joinPoint.proceed(); } }
Nous utiliserons l'indicateur de fonctionnalité ci-dessus avec le contrôleur comme ceci :
@Component @RequiredArgsConstructor public class FeatureAFeatureFlag implements FeatureFlagValidator { private final FeatureFlagConfigs featureFlagConfigs; private final Logger logger = LoggerFactory.getLogger(FeatureAFeatureFlag.class); @Override public boolean validate(Object... args) { boolean result = featureFlagConfigs.getFeatureAEnabled(); if (!result) { logger.error("Feature A is not enabled!"); } return result; } }
De cette façon, nous pouvons créer nos indicateurs de fonctionnalités personnalisés dans Spring Boot. Nous avons créé des indicateurs de fonctionnalités de manière à pouvoir les étendre et nous pouvons ajouter plusieurs façons de basculer entre les fonctionnalités. L'approche ci-dessus peut également être modifiée et à l'intérieur des validateurs d'indicateurs de fonctionnalités, nous pouvons également utiliser une table de base de données pour basculer les fonctionnalités. Ce tableau peut être géré à l'aide d'un panneau d'administration.
Si vous êtes arrivé jusqu’ici, je vous remercie de tout cœur pour votre temps. J'espère que vous avez trouvé cet article qui valait l'investissement. Vos commentaires sont très appréciés. Merci! Bon apprentissage !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!