Programmation orientée aspect avec Spring
Introduction
La programmation orientée aspect (AOP) introduit des concepts de transversalité qui vont au-delà de ce qui est typiquement offert par la programmation orientée objet (POO).
L’AOP se concentre sur les « aspects », qui sont des modules dédiés à des préoccupations transversales, c’est-à-dire des fonctionnalités ou des comportements qui ne sont pas liés à la logique métier principale d’une application, mais qui sont répandus à travers plusieurs composants ou classes. Ces aspects permettent d’ajouter des traitements spécifiques qui s’exécutent en réponse à certains types d’événements ou d’opérations sur un ensemble d’objets. Par exemple, un aspect peut être déclenché à chaque appel d’une méthode sur des classes spécifiques. Un exemple classique de préoccupation transversale est la gestion des transactions. Avec l’AOP, il est possible d’ajouter une gestion de transaction de manière uniforme et centralisée à diverses parties d’une application. Spring utilise l’AOP de manière transparente pour implémenter certaines fonctionnalités. Par exemple, la gestion des transactions et la sécurité sont souvent gérées via AOP dans Spring. L’inclusion de la librairie Spring AOP dans un projet est optionnelle et dépend des besoins spécifiques du projet.
Bien que l’AOP soit souvent présente dans les frameworks utilisés par les clients, elle est rarement employée pour coder des règles métier directement, en raison de ses exigences en matière de conception. Pour des fonctionnalités qui impliquent plusieurs entités, une approche plus traditionnelle comme le copier/coller est souvent préférée en raison de sa simplicité.
L’AOP apporte une dimension supplémentaire à la conception de logiciels en permettant une gestion élégante et efficace des préoccupations transversales. Bien que son utilisation nécessite une réflexion spécifique en matière de conception, elle offre des avantages significatifs en termes de modularité...
Pourquoi l’AOP ?
Dans le contexte de Spring Framework et la programmation orientée aspect (AOP), il existe différentes approches et bibliothèques pour gérer les aspects, allant des utilisations simples et standardisées aux cas d’utilisation plus avancés.
Pour les cas d’utilisation simples et standards, Spring offre une bibliothèque AOP intégrée. Pour des utilisations plus avancées, Spring supporte l’intégration avec AspectJ, une bibliothèque puissante pour l’AOP qui se base sur les annotations et offre des fonctionnalités étendues.
Tout comme la configuration traditionnelle du contexte Spring, la définition des aspects peut se faire via des fichiers XML, des annotations, ou une combinaison des deux. Un exemple courant est l’utilisation de l’annotation @Transactional de Spring, qui est un aspect géré directement par Spring pour la gestion des transactions.
Les aspects sont souvent intégrés dans le socle technique d’une application et sont utilisés pour des préoccupations transversales comme l’instrumentation du code. Ils sont rarement employés pour des préoccupations métier en raison de la complexité et des défis de maintenance que peut présenter ce type de programmation. Le code AOP doit être soigneusement écrit et bien...
Concepts d’AOP
Spring utilise la terminologie standard pour nommer ses éléments relatifs à l’AOP même si elle n’est pas très intuitive.
Définitions
Termes standards pour la programmation orientée aspect dans Spring :
Aspect : module de préoccupations transversales qui impacte un ensemble de classes.
Join Point : point spécifique dans l’exécution du programme, comme l’exécution d’une méthode ou le traitement d’une exception. Dans Spring AOP, un join point représente toujours l’exécution d’une méthode.
Advice : action exécutée par un aspect à un join point. Les types courants d’advices sont before, after, et around. Les advices peuvent être chaînés.
Pointcut : prédicat pour identifier des join points, souvent exprimé par une expression de langage (comme celui d’AspectJ) spécifiant, par exemple, le nom d’une méthode.
Introduction : ajout dynamique de champs et de méthodes supplémentaires dans un objet. Spring AOP permet également d’introduire de nouvelles interfaces avec leurs implémentations. Dans AspectJ, cela est connu comme une déclaration « inter-types ».
Target Object : objet ciblé par un ou plusieurs aspects, souvent appelé...
Limites de Spring AOP et utilisation d’AspectJ
Spring AOP est conçu principalement pour l’interception et la manipulation des appels de méthode, ce qui est suffisant pour de nombreux scénarios d’utilisation courants. Cependant, il a certaines limitations, notamment dans le contexte de l’interception des modifications d’état des champs d’objets. Spring AOP se concentre sur les join points qui sont essentiellement des appels de méthode. Cela signifie que Spring AOP peut intercepter et manipuler les opérations lorsqu’une méthode est invoquée sur un objet. Par contre, Spring AOP ne prend pas en charge l’interception des modifications de l’état des champs des objets. Par exemple, si une propriété d’un objet change, Spring AOP ne peut pas intercepter cette modification directement.
Pour des cas d’utilisation plus avancés, comme l’interception des changements d’état des champs, il est recommandé d’utiliser directement AspectJ. AspectJ est un framework AOP plus puissant et plus flexible, capable d’intercepter une plus grande variété de join points, y compris les modifications des champs.
Imaginons que vous ayez une classe User avec un champ name. Avec Spring AOP, vous pouvez facilement intercepter une méthode setName pour suivre quand le nom de l’utilisateur est modifié.
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
}
En utilisant Spring AOP, vous pouvez créer un aspect qui intercepte l’appel à setName pour enregistrer ou effectuer une action chaque fois que le nom est modifié. Cependant, si vous devez intercepter directement toute modification du champ name sans passer par un setter, vous devriez alors utiliser AspectJ, car Spring AOP ne supporte pas ce type d’interception. Le support @AspectJ dans Spring permet aux développeurs d’appliquer des aspects transversaux comme la gestion des transactions...
API bas niveau pour Spring AOP
Voici un exemple d’utilisation des API de bas niveau. Nous ne les montrerons pas toutes, car elles sont très bien présentées dans la documentation Spring et nous ne nous en servirons que très rarement. Nous les mentionnons, car elles permettent d’expérimenter les aspects très simplement.
1. Interface PointCut
L’interface PointCut correspond à un point de coupe, qui permet grâce à une expression régulière d’identifier les méthodes qui seront interceptées.
class MonPointcut implements PointCut {
public ClassFilter getClassFilter() {
return null;
}
public MethodMatcher getMethodMatcher() {
return null;
}
Il y a deux méthodes dans l’interface :
Classe |
Méthode |
Utilité |
ClassFilter |
getClassFilter(); |
Filtre sur la classe |
MethodMatcher |
getMethodMatcher(); |
Matcher sur la classe |
2. Interface ClassFilter
L’interface ClassFilter ne contient qu’une méthode qui correspond à celle qui sera appelée lors de l’interception.
class MonClassFilter implements ClassFilter {
public boolean matches(Class<?> clazz) {
return...
Pour aller plus loin
Il existe des librairies tirerces qui peuvent aider pour l’AOP.
1. Librairie Java jcabi-aspects
La librairie Java jcabi-aspects, basée sur AspectJ, enrichit les possibilités d’AOP au-delà de ce qui est disponible avec Spring ou Lombok. Elle propose des annotations comme @Async, @Cachable, et @Loggable, ainsi que des fonctionnalités supplémentaires non couvertes par ces frameworks, telles que @LogExceptions, @Quietly, @RetryOnFailure, et @UnitedThrow. Ces annotations permettent d’ajouter facilement des comportements cross-cutting (transversaux), comme la journalisation des exceptions ou la répétition des opérations en cas d’échec. Pour plus d’informations et des exemples, vous pouvez consulter leur documentation sur : https://aspects.jcabi.com/
2. Métriques AspectJ
Il existe une librairie qui permet d’ajouter des métriques dans nos backends via des annotations AspectJ. Elles permettent d’avoir des éléments fins sur les appels. La documentation est disponible ici : https://github.com/astefanutti/metrics-aspectj.
La librairie "metrics-aspectj" offre une solution pour intégrer des métriques dans les applications backend en utilisant des annotations basées sur AspectJ. Elle permet de collecter des données détaillées sur les performances et les comportements des appels de méthodes...
Points clés
Points à retenir :
-
La programmation orientée aspect est souvent présente dans les socles logiciels.
-
Il est possible de coder simplement des aspects.
-
Si on retrouve une action sur un groupe de classes, il faut voir si on peut utiliser un aspect.
-
Les aspects sont déroutants, il faut bien les comprendre pour pouvoir corriger le code qui les utilise.