Tissage dans la programmation orientée aspect
From Wikipedia, the free encyclopedia
Le tissage est l'étape de la programmation orientée aspect qui a pour but d'insérer des bouts de codes appelés greffons (Advice) dans le code métier d'une application. Tisser un greffon dans une méthode revient à redéfinir la méthode comme la composition de son corps avec le greffon[1]. Le tissage d'aspects au niveau de l'application est un mécanisme offrant l'extensibilité et l'adaptabilité, permettant ainsi à l'application de s'adapter facilement quand des nouveaux besoins font surface[2].
Tisser un aspect peut se faire à plusieurs moments : à la compilation, au chargement et à l'exécution. Il existe de nombreux tisseurs dans différents langages mais c'est en Java que l'on trouve les tisseurs les plus matures (utilisabilité, stabilité, performances, intégration aux outils...).
- Aspect
- Un aspect est une entité logicielle qui capture une fonctionnalité transversale à une application[3]. C'est généralement un ensemble de greffons et de points de coupe d'un logiciel.
- Greffon (advice)
- C'est un bloc de code définissant le comportement d'un aspect[4]. Ce bloc de code est destiné à être exécuté au niveau d’un point de coupe avant, après ou autour du point de jonction.
- Point coupe
- Une coupe (pointcut) désigne un ensemble de points de jonction[4].
- Point de jonction
- Un point de jonction(join point) est un point dans l'exécution du programme où un ou plusieurs aspects peuvent être ajoutés[4].Endroit où des aspects peuvent être ajoutés (Méthode, constructeur, Exceptions...)
- Join point shadows[5]
- est la projection statique d'un point de jonction, sur le code du programme.
- Déclaration inter-type
- C'est moyen par lequel un aspect ajoute des informations comme des nouvelles propriétés, des nouvelles méthodes ou des interfaces à une classe existante, permettant ainsi d'étendre cette dernière.
- Le tissage statique
- s'effectue à la compilation ou au chargement. Une fois un aspect tissé, il est impossible de le retirer. Lors ce tissage, le code aspect est fusionné avec le code métier[6],[7]:
- soit pour donner un nouveau code source.
- soit pour donner un pseudo-code intermédiaire.
- Le tissage dynamique[8]
- permet de garder les aspects et le code applicatif complètement séparés. Ainsi, l'exécution, les aspects peuvent être tissés, donc ajoutés au code ou retirés. Cela accroît l’intérêt porté sur la POA pour le prototypage et le test rapides, car on n'a plus besoin de ré-compiler, redéployer et relancer l'application.
Tissage
Le tissage classique basé sur les ombres de point de jointures (join point shadows) comme emplacement de tissage a un problème:efficacité de compilation. Le tissage basé sur les enveloppes[9] vise à diminuer le nombre des emplacements de tissage et par conséquent, la surcharge du au tissage, en introduisant des accesseurs(getter et setter) pour les champs et des proxys pour les méthodes de classes. L'intérêt de cette technique est à trois niveaux. Premièrement, la simplification de la recherche des emplacements de tissage, ceux-ci sont placés dans les enveloppes. Deuxièmement, la diminution du nombre des actions de tissage, car un aspect est tissé une seule fois par champs affecté et troisièmement, simplification du processus de tissage, car on ne se préoccupe plus de maintenir le contrôle de structure des méthodes affectées par le tissage. Grâce à la compilation à temps (just in time), l’indirection introduite par cette technique à un impact faible sur la performance lors de l'exécution. Elle est un complément au tissage statique classique et bien adaptée pour la phase “compilation-teste-debogage”.
Tissage à la compilation
Le tissage à la compilation est le plus simple. Il consiste, à prendre le code applicatif et les aspects en entrée et de produire un code mélangé apportant les nouvelles fonctionnalités. Pour ce faire, une étape de pré compilation est nécessaire ou alors, un tisseur est couplé au compilateur. Cette approche produit un code qui demandera moins de contrôles à l'exécution du fait du travail accompli par le compilateur. Ce tissage est obligatoire si les aspects ajoutent des informations nécessaire à la compilation des classes comme de nouveaux champs ou nouvelles méthodes.
Tissage au chargement
Ajouter des nouvelles fonctionnalités aux composants existants sous format binaire se fait par instrumentation du code. Ainsi le tissage se fait au moment où le chargeur de classes charge le code dans la machine virtuel Java (JVM).
Tissage à l'exécution
Cette approche permet de changer le comportement du programme à l'exécution. Pour y parvenir, le support de tissage et d'exécution des aspects est placé directement dans l’environnement d'exécution. L'environnement d'exécution[8], comme la JVM adapté aspects, fournit une interface pour le tissage des aspects pendant l'exécution permettant de changer le modèle d'exécution d'une application.
Tisseurs
Un élément central de la POA est le tisseur. Étant donné un ensemble de programmes ciblés et un ensemble d'aspects définis, le tisseur transforme le programme cible à tisser en un programme enrichi par ces aspects selon certaines contraintes[10]. Il existe plusieurs tisseurs en java. Nous allons considérer ici, les tisseurs les plus connus.
AspectJ
AspectJ[11] est le framework orienté aspect le plus connu. Son mode tissage était purement statique avant sa fusion avec AspectWerkz[12],[13]en . Cette fusion a permis à AspectJ de faire du tissage dynamique, mais au chargement seulement, et de se doter des annotions dans la mise en œuvre des aspects.
À la compilation, le compilateur AspectJ appelé ajc prend en entrée le code aspect et le code métier et produit en sortie un byte-code tissé. Il est aussi capable de faire de la post-compilation en tissant des aspects dans les fichiers de classe compilés ou dans les fichiers JAR. Ce compilateur est divisé en deux parties, une partie front-end et une back-end[14]. Le front-end, est cette partie qui reçoit en entrée le code aspects et le code métier et qui produit un byte-code annoté avec les informations représentants tout ce qui n'est pas du java pur comme les greffons et les points de coupe. Le back-end quant à lui prend ce byte code annoté et implémente les transformations basées sur ces informations et produit les fichiers de classes tissés. Ces transformations consistent à instrumenter le code en insérant les appels aux méthodes de greffons déjà précompilés.
Pour faire le tissage au chargement, AspectJ utilise un agent de chargement et une configuration fourni sous fichier xml. Cet agent est un chargeur de classe spécial permet d'intervenir au niveau du byte-code. L'agent enrichit donc le code de la classe avec le code d'aspects, pendant le chargement de la classe dans la JVM.
JBoss
JBoss[15] offre un service, nommé JBoss AOP, afin d'utiliser les concepts de l'AOP. C'est une équipe dirigé par Bill Bruke qui est à l'origine du framework, ces droits furent rachetés en 2004 par Red Hat. Avec Jboss AOP il y a deux façons de créer des greffons
- en utilisant un ensemble d'aspect prédéfinis, mais certains ne peuvent d'être utilisé qu'avec JBoss Application Server.
- en les créant.
Les aspects avec JBoss AOP, sont écrits en Java pur sans extension syntaxique mais nécessite l'utilisation d'une API propre à JBoss AOP. Un aspect se compose obligatoirement de deux fichiers :
- le premier contient le code du greffon, appelé intercepteur en JBoss
- le deuxième est un fichier xml. Ce fichier permet de configurer les coupes et d'assurer le déploiement à chaud des aspects au cours de l'exécution.
Avec JBoss AOP le tissage peut être :
- statique : pour cela il faut déclarer lier l'intercepteur et le point de jonction en utilisant la balise
<bind> - dynamique : en utilisant la balise
<prepare>mais avant cela il faut configurer la Machine Virtuelle Java pour supporter l'échange à chaud(HotSwapping). L'activation du HotSwap permet d'instrumenter le bytecode des intercepteurs durant l'exécution[16].
Spring
Spring[17] propose un framework, nommé Spring AOP[18], permettant d'utiliser les concepts de la POA. Cependant, le support de la POA proposé par Spring est plus limité que celui d’AspectJ en termes de points de jonction pour définir les coupes, mais Spring à la capacité d'utiliser les aspects développé en AspectJ.
Avec Spring, les greffons sont implémentés sous forme d'une classe java implémentant une certaine interface, selon le type de greffon voulu, sa déclaration se fait à l'aide d'un bean dans le fichier de configuration. Dans ce fichier il faut déclarer également un bean pour spécifier le point de coupe et un autre pour lier le greffon au point de coupe. La portée des aspects est limitée avec Spring, seules les classes définies sous forme de bean peuvent être interceptées.
Il existe trois façons pour définir un point de coupe en Spring AOP:
- avec le nom des méthodes à intercepter.
- avec des expressions régulières pour désigner les méthodes à intercepter.
- avec AspectJ.
Avec Spring AOP, de base les aspects sont tissés au chargement qui se réfère au processus de tissage d'AspectJ, le tissage s'effectue à l'aide de la création dynamique de proxy pour les beans dont les méthodes doivent être interceptées. La génération de ces proxy se fait dans le fichier de configuration. Mais on peut également modifier les greffons pendant l'exécution du programme en paramétrant le fichier de configuration.
JAC
JAC[19],[20] (Java Aspect Components) est un framework de POA et non un nouveau langage dans lequel la notion de centrale est le composant aspect. Il offre deux niveaux de POA permettant soit de programmer totalement de nouveaux aspects soit de configurer les aspects préprogrammés pour les adapter aux besoins. Un point de coupe est composé de quatre expressions de correspondance à savoir objets, classes, méthodes et hébergeurs. Pour développer un composant aspect, il faut définir des points de coupe et les associer aux méthodes d’encapsulations définies dans les classes adaptateurs Wrapper.
Avec JAC on peut aussi configurer les aspects, en associant à chaque composant aspect un fichier texte décrivant le configuration. Pour effectuer le tissage à l'exécution, le tisseur doit faire une réflexion sur le code métier pour décider si une méthode ou une propriété doit être encapsulé ou pas. Ces décisions sont prises en se basant sur les définitions des points de coupe. Pour y parvenir, un ensemble d’informations sur le code métier sont sauvegardées en mémoire et construites lors du chargement de l’application. Les adaptateurs dynamiques reposent sur le Protocole à méta-objets, permettant d’insérer des crochets dans les adaptateurs lors du chargement. Ces crochets sont des invocations de réflexion qui permettent à la méthode encapsulée être résolue lors de l'exécution. Ainsi un API permettant d’avoir des informations de type à l'exécution peut les accéder.
Contrairement à AspectJ qui traite les aspects au niveau des classes, les instances d'une même classe dans JAC peuvent être modifiées différemment[21]. Grâce aux quatre expressions composant le point de coupe, la granularité est au niveau de l'objet.