Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parVivien Brunelle Modifié depuis plus de 9 années
1
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 1 - Seconde partie Un exemple de programmation orientée Aspect avec AspectJ
2
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 2 - AspectJ est un langage aspects, points de jointure, advices, … sont des extensions syntaxiques de Java une approche par transformation de code compilateur ajc (remplace javac) => nécessite le code source les.class générés par ajc sont compatibles avec toute JVM statique => performant mais peu flexible supporté par des IDE (emacs, JBuilder, Forte 4J, Eclipse) open source et gratuit
3
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 3 - Un éditeur de figure operations that move elements factory methods Display * 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) Figure makePoint(..) makeLine(..) FigureElement moveBy(int, int)
4
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 4 - Un éditeur de figure class Line implements FigureElement{ private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; } void setP2(Point p2) { this.p2 = p2; } void moveBy(int dx, int dy) {... } } class Point implements FigureElement { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; } void moveBy(int dx, int dy) {... } }
5
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 5 - a Line a Point Où sont les points de jointure (join points) ? returning or throwing dispatch a method call returning or throwing a method execution returning or throwing a method execution Un appel : l.moveBy(2, 2)
6
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 6 - Les coupes (pointcuts) Un moyen d’identifier un ensemble de points de jointure Une coupe est un prédicat sur les points de jointure Primitives de coupes disponibles : call, execution initialization, preinitialization, staticinitialization get, set handler within, withincode cflow, cflowbelow this, target, args...
7
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 7 - Combinaison des primitives de coupe or a “void Line.setP2(Point)” call a “void Line.setP1(Point)” call call(void Line.setP1(Point)) || call(void Line.setP2(Point)); Utilisation de &&, || et ! comme pour les prédicats
8
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 8 - Type d’advices Des actions supplémentaires à faire lorsqu’une coupe est identifiée before pour ajouter des actions avant after pour ajouter des actions après after returning sur retour normal after throwing sur retour avec erreur around pour prendre le control sur l’exécution du point de jointure
9
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 9 - Coupe anonyme ou non dans un advice pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); Nom de coupe Paramètres de coupe after() returning: call(void Line.setP1(Point)) || call(void Line.setP2(Point)) { Display.update(); } after() returning: move() { Display.update(); } Coupe anonyme Utilisation de la coupe définie
10
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 10 - Exemple d’aspect : Rafraîchissement d’image collection of figure elements that move periodically must refresh the display as needed complex collection asynchronous events we will initially assume just a single display
11
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 11 - Rafraîchissement sans et avec AspectJ class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(); } void setP2(Point p2) { this.p2 = p2; Display.update(); } aspect DisplayUpdating { pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)); after() returning: move() { Display.update(); } DisplayUpdatingV1
12
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 12 - Les coupes peuvent concernées plusieurs classes aspect DisplayUpdating { pointcut move(): call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int)); after() returning: move() { Display.update(); } class Line { private Point p1, p2; Point getP1() { return p1; } Point getP2() { return p2; } void setP1(Point p1) { this.p1 = p1; Display.update(); } void setP2(Point p2) { this.p2 = p2; Display.update(); } void moveBy(int dx, int dy) { … } } class Point { private int x = 0, y = 0; int getX() { return x; } int getY() { return y; } void setX(int x) { this.x = x; Display.update(); } void setY(int y) { this.y = y; Display.update(); } void moveBy(int dx, int dy) { … } } DisplayUpdatingV2
13
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 13 - Primitive de coupe “this”/“target” this/target(VarName | TypeName) permet de : - tester dynamiquement le type de l’objet courant/de la cible (restreint la coupe) this(Point), target(Line) - récupérer l’objet courant/la cible du point de jointure en cours (ne restreint pas la coupe) this(myLine), target(myPoint) Valeur de variable extraite de la droite vers la gauche du ‘:’ du target vers la coupe définie par l’utilisateur de la coupe vers l’advice, et donc dans le corps de l’advice pointcut move(Line l): target(l) && (call(void Line.setP1(Point)) || call(void Line.setP2(Point))); after(Line line) returning: move(line) {... }
14
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 14 - Gestion du contexte utilisant “target” aspect DisplayUpdating { pointcut move(FigureElement figElt): target(figElt) && (call(void FigureElement.moveBy(int, int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point)) || call(void Point.setX(int)) || call(void Point.setY(int))); after(FigureElement fe) returning: move(fe) { Display.update(fe); } figElt est lié à FigureElement dans la coupe “move” fe est lié à FigureElement dans l’advice DisplayUpdatingV3
15
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 15 - Primitive de coupe “args” aspect PointBoundsPreCondition { before(int newX): call(void Point.setX(int)) && args(newX) { assert newX >= MIN_X; assert newX <= MAX_X; } before(int newY): call(void Point.setY(int)) && args(newY) { assert newY >= MIN_Y; assert newY <= MAX_Y; } aspect PointBoundsPostCondition { after(Point p, int newX) returning: call(void Point.setX(int)) && target(p) && args(newX) { assert p.getX() == newX; } after(Point p, int newY) returning: call(void Point.setY(int)) && target(p) && args(newY) { assert p.getY() == newY; } Vérification de contrats Même principe que target et this mais pour les paramètres du point de jointure
16
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 16 - Méthode spéciale “proceed” Utilisée dans les advices de type “around” ReturnType around(T1 arg1, T2 arg2, …) La méthode proceed ReturnType proceed(T1, T2, …) Permet d’exécuter ce qui aurait été exécuté si l’advice n’avait pas été défini Même type de paramètres et même type de retour
17
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 17 - Méthode spéciale “proceed” aspect PointBoundsEnforcement { void around(int newX): call(void Point.setX(int)) && args(newX) { proceed( clip(newX, MIN_X, MAX_X) ); } void around(int newY): call(void Point.setY(int)) && args(newY) { proceed( clip(newY, MIN_Y, MAX_Y) ); } private int clip(int val, int min, int max) { return Math.max(min, Math.min(max, val)); } Gestion des bornes
18
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 18 - Déclaration de méthodes et d’attributs aspect PointCaching { private MyLookupTable cache = new MyLookupTable(); Point around(int x, int y): call(Point.new(int, int)) && args(x, y) { Point ret = cache.lookup(x, y); if (ret == null) { ret = proceed(x, y); cache.add(x, y, ret); } return ret; } Gestion d’un cache
19
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 19 - aspect DisplayUpdating { private Display FigureElement.display; static void setDisplay(FigureElement fe, Display d) { fe.display = d; } pointcut move(FigureElement figElt): ; after(FigureElement fe): move(fe) { fe.display.update(); } Un afficheur par element de figure DisplayUpdating v4 display est un attribut dans les objets de type FigureElement, mais : appartient à l’aspect DisplayUpdating DisplayUpdating doit fournir getter/setter (appelé dans le code de setup) Déclaration de méthodes et d’attributs
20
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 20 - Généricité des coupes target(Point) target(graphics.geom.Point) target(graphics.geom.*) tout type dans graphics.geom target(graphics..*) tout type dans un sous-package de graphics call(void Point.setX(int)) call(public * Point.*(..)) toute méthode publique de Point call(public * *(..)) toute méthode publique de n’importe quel type call(void Point.setX(int)) call(void Point.setY(*)) call(void Point.set*(*)) call(void set*(*)) tout mutateur call(Point.new(int, int)) call(new(..)) tout constructeur
21
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 21 - Access réflexif au point de jointure courant Disponible dans les advices thisJoinPoint.getSignature(), thisJoinPoint.getArgs(),... aspect PublicErrorLogging { Logger log = Logger.global; pointcut publicInterface(): call(public * graphics..*.*(..)); after() throwing (Error e): publicInterface() { Method m = thisJoinPoint.getSignature(); log.throwing( m.getDeclaringType().getName(), m.getName(), e); } thisJoinPoint permet de savoir où l’advice s’exécute
22
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 22 - Initialization/ preinitialization/ staticinitialization ( Pointcut ) initialization(Foo.new(int)) l’initialisation qui débute avec le constructeur Foo.new(int) preinitialization(Foo.new(int)) comme initialisation mais avant que le constructeur de super soit appelé staticinitialization(Foo.new(int)) quand le type Foo est initialisé après le chargement de la classe D’autres primitives de coupes : contrôle des initialisations
23
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 23 - D’autres primitives de coupes within( TypeName ) withincode( MemberSignature ) Tout point de jointure tel que : - le code en cours d’exécution est défini dans le type TypeName - le code en cours d’exécution est défini dans la méthode ou contructeur dont la signature est MemberSignature get( int Point.x ) set( int Point.x ) Accès à un attribut en lecture/écriture
24
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 24 - all join points on this slide are within the control flow of this join point a Point a Line a Point Flot de contrôle et point de jointure Un appel : l.moveBy(2, 2)
25
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 25 - cflow( Pointcut ) tous les points de jointure dans le flot de contrôle du point de jointure Pointcut cflowbelow( Pointcut ) tous les points de jointure au dessous du flot de contrôle du point de jointure Pointcut D’autres primitives de coupes
26
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 26 - Composition d’aspects Qu’est ce qu’il se passe si 2 « advices » sont appliqués au même point de jointure ? aspect Security { before(): call(public *(..)) { if (!Policy.isAllowed( thisJoinPoint )) throw new SecurityExn(); } } aspect Logging { before(): logged() { System.err.println("Entering " + thisJoinPoint ); } pointcut logged(): call(void troublesomeMethod()); }
27
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 27 - Composition d’aspects Ordre indéfini sauf dans un même aspect, dans les sous aspects, en déclarent une règle de précédence aspect Security { before(): call(public *(..)) { if (!Policy.isAllowed( thisJoinPoint )) throw new SecurityException(); } declare precedence: Security, *; } aspect Logging { pointcut logged(): call(void troublesomeMethod()); before(): logged() { System.err.println("Entering " + thisJoinPoint ); }
28
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 28 - plug in: unplug: “Plug & debug” ajc Point.java Line.java TraceSupport.java Tracing.java Activer/désactiver la trace sans éditer les classes Pas de coût d’exécution quand désactivé
29
Séparation des préoccupations (c) 2004, Audrey Occello, LF8 MOC.. - 29 - Conclusion Bonne modularité Code + naturel, + petit, - mélangé Maintenance et évolution + facile application + facile à comprendre, à débugger, à changer Réutilisation facilitée ajout/retrait d’aspects aspects abstraits
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.