1 / 56

AOP mit AspectJ

AOP mit AspectJ. Inhalt. Übersicht Einführung in AOP AOP mit AspectJ Kurzübersicht AspectJ Wie identifiziert AspectJ Stellen im Programmfluss? Wie definiert man, was an diesen Stellen passiert? Das neue Modul für crosscutting concerns: aspect Vertiefung in AspectJ Pointcut Advice

miya
Download Presentation

AOP mit AspectJ

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. AOP mit AspectJ

  2. Inhalt • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Aspect • Kontext eines joinpoints an den advice weiterreichen

  3. Modul 3 Modul 4 Modul 2 Modul 1 Module beim Software Entwurf • Anforderungen werden definiert und einem Modul zugeordnet • Module kommunizieren über eine definierte Schnittstelle • Die Abhängigkeiten, die dabei entstehen, sollten gering gehalten werden • Gängige Techniken wie Prozedurale Programmierung, OOP und Design Patterns helfen bei dieser Art von Modularisierung

  4. Module mit systemweiten Abhängig-keiten („crosscutting concerns“) • Es gibt Anforderungen, die es nötig machen aus sehr vielen Modulen auf ein anderes Modul zuzugreifen. Z.B. • Bestimmte Aktionen sollen geloggt werden • Bestimmte Aktionen erfordern die Autorisation des Benutzers • Selbst wenn man ein Log-Modul oder ein Autorisations-Modul existiert, muss man immer noch in vielen Modulen darauf zugreifen Modul 3 Modul 4 Log-Modul Modul 2 Modul 1 Autorisations-Modul

  5. Probleme mit konventionellen Techniken • das Log-Modul z.B. kann seine Schnittstelle ändern • es muss an sehr vielen Stellen der Code angepasst werden • jeder Entwickler eines Moduls muss sich daran halten, .z.B. mit dem Log-Modul zu kommunizieren • fehleranfällig • Systemweite Anforderungen können hinzukommen oder sich ändern • es muss an sehr vielen Stellen der Code angepasst werden • der Code, der die eigentliche core logic implementiert wird unübersichtlicher Fazit: systemweite Anforderungen können mit konventionellen Techniken wie OOP nicht vernünftig modularisiert werden

  6. Beispiel – core logic package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  7. Beispiel – Log Modul package example2; import java.util.Date; publicclass LogModule { publicstaticvoid logPublicMethodExecutionBegin(String methodName) { System.out.println(new Date() + ": public method " + methodName + " begin"); } publicstaticvoid logPublicMethodExecutionEnd(String methodName) { System.out.println(new Date() + ": public method " + methodName + " end"); } publicstaticvoid logPrivateMethodExecutionBegin(String methodName) { System.out.println(new Date() + ": private method " + methodName + " begin"); } publicstaticvoid logPrivateMethodExecutionEnd(String methodName) { System.out.println(new Date() + ": private method " + methodName + " end"); } }

  8. Beispiel – Logmodul aufrufen package example2; publicclass Module1 { privatestaticint answer; publicstaticvoid method1() { LogModule.logPublicMethodExecutionBegin("method1"); print("hello world!" + answer); LogModule.logPublicMethodExecutionEnd("method1"); } publicstaticvoid method2() { LogModule.logPublicMethodExecutionBegin("method2"); answer = 42; LogModule.logPublicMethodExecutionEnd("method2"); } privatestaticvoid print(String s) { LogModule.logPrivateMethodExecutionBegin("print"); System.out.println("printing: " + s); LogModule.logPrivateMethodExecutionEnd("print"); } }

  9. Beispiel – Logmodul aufrufen (2) package example2; publicclass Module2 { publicstaticvoid method3() { LogModule.logPublicMethodExecutionBegin("method3"); Module1.method1(); LogModule.logPublicMethodExecutionEnd("method3"); return 42; } }

  10. Aspektorientierte Programmierung Modul 3 Modul 4 Modul 2 Log-Aspekt Log-Modul Modul 1

  11. Aspektorientierte Programmierung • Bietet als Lösung für „crosscutting concerns“ eine neue Art von Modul: den Aspekt • Dieser definiert an zentraler Stelle „was“ „wann“ geschehen soll („weaving rules“) • Ein „aspect-weaver“ konstruiert aus der core logic und den Aspekten ein neues System, das • weiterhin die Kernanforderungen erfüllt • die systemweiten Anforderungen erfüllt • Die core logic wird weiterhin mit konventioneller Technik implementiert • Die core logic weiß nichts davon, dass zusätzliche Funktionalität „eingebaut“ wird

  12. AOP mit AspectJ • AOP ist wie z.B. OOP eine Methode zu programmieren • Es gibt verschiedene Implementierungen • Bei OOP z.B. C++, Java, Smalltalk • Bei AOP gibt es z.B. AspectJ • AspectJ • benutzt Java, um die core logic zu implementieren • erweitert die Sprache Java um die Möglichkeit Aspekte mit ihren weaving rules zu implementieren • bietet einen Compiler (ajc) an, der den aspect weaver darstellt • erzeugt Java-Bytecode, der auf jeder JVM läuft • ist in Eclipse mit dem plugin ajdt vertreten

  13. Wo sind wir? • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Aspect • Kontext eines joinpoints an den advice weiterreichen

  14. Wie identifiziert AspectJ Stellen im Programmfluss? • Joinpoints sind alle Stellen im Programm, die im Programmfluss erreicht werden • Methoden-Aufrufe • Konstruktor-Aufrufe • Variablenzuweisungen • das Werfen einer Exception usw.

  15. Joinpoints: Methodenaufruf package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Alle Aufrufe der public static Methode method1() in der Klasse example1.Module1 call(public static void example1.Module1.method1()) package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  16. Joinpoints: Methodenausführung package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Ausführung der publicstatic Methode method1() in der Klasse example1.Module1 execution(public static void example1.Module1.method1()) package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  17. execution(public * example1.Module1.*()) Joinpoints mit Wildcards package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Ausführung aller publicMethoden in der Klasse example1.Module1 mit beliebigem Rückgabetyp package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  18. Joinpoints: Parameter festlegen package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Ausführung aller Methoden in der Klasse example1.Module1 die genau einen Parameter vom Typ String entgegennehmen execution(* example1.Module1.*(String)) package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  19. execution(public * example1.*.*(..)) Joinpoints: Parameter mit Wildcards package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Ausführung aller publicMethoden im Package example1, die beliebige Parameter nehmen package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  20. Joinpoints: lesender Feldzugriff package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Jeder lesende Zugriff auf das privatestatic Feld answer in der Klasse example1.Module1 get(private static int example1.Module1.answer) package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  21. Joinpoints: schreibender Feldzugriff package example1; publicclass Module1 { privateint answer; publicstaticvoid method1() { print("hello world! “ + answer); } publicstaticvoid method2() { answer=42; } privatestaticvoid print(String s) { System.out.println("printing: " + s); } } Jeder schreibende Zugriff auf das privatestatic Feld answer in der Klasse example1.Module1 set(private static int example1.Module1.answer) package example1; publicclass Module2 { publicstaticint method3() { Module1.method1(); return 42; } } package example1; publicclass Test { publicstaticvoid main(String[] args) { Module1.method1(); Module1.method2(); Module2.method3(); } }

  22. pointcut executionOfMethod1() : execution(* example1.Module1.method1()) Schlüsselwort Name Primitiver pointcut Pointcut • Ein Pointcut definiert eine Menge von jointpoints, an denen neue Funktionalität „eingebaut“ werden soll. • Man spricht dabei vom „Abfangen“ (engl. capture) von jointpoints

  23. pointcut executionOfMethod1OrMethod2() : executionOfMethod1() || execution(* example1.Module1.method2()) Oben definierter pointcut Neuer primitiver pointcut Verknüpfung von pointcuts • Pointcuts können mit booleschen Operatoren verknüpft werden, um andere Mengen von joinpoints abzufangen

  24. Wo sind wir? • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Aspect • Kontext eines joinpoints an den advice weiterreichen

  25. Wie definiert man, was passieren soll, wenn ein joinpoint abgefangen wird? • Die Aktion, die ausgeführt werden soll heißt in AspectJ advice • Es gibt drei Varianten von advice: Aktion wird • vor dem joinpoint ausgeführt (before) • nach dem joinpoint ausgeführt (after) • um die Ausführung des joinpoints herum ausgeführt (around). Diese Variante kann den joinpoint sogar umgehen

  26. Schlüsselwort pointcut before() : executionOfMethod1OrMethod2 () { LogModule.logPublicMethodExecutionBegin (thisJoinPoint.getSignature().getName()); } Block mit Java-Code Definition von advice • before advice

  27. Definition von advice • around adivce Rückgabetyp entspricht dem des joinpoints void around() : executionOfMethod1OrMethod2 () { LogModule.logPublicMethodExecutionBegin (thisJoinPoint.getSignature().getName()); proceed(); LogModule.logPublicMethodExecutionEnd (thisJoinPoint.getSignature().getName()); } Schlüsselwort proceed() führt den joinpoint aus. Kann weggelassen werden zum Überspringen des joinpoints.

  28. Wo sind wir? • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Aspect • Kontext eines joinpoints an den advice weiterreichen

  29. Das neue Modul für crosscutting concerns: aspect • AspectJ führt den aspect ein, eine logische Einheit vergleichbar mit einer Klasse, die pointcuts und advices enthält. publicaspect SimpleLogAspect { }

  30. Das neue Modul für crosscutting concerns: aspect • AspectJ führt den aspect ein, eine logische Einheit vergleichbar mit einer Klasse, die pointcuts und advices enthält. publicaspect SimpleLogAspect { pointcut publicMethodExecution() : execution(public * *.Module*.* (..)); pointcut privateMethodExecution() : execution(private * *.Module*+.* (..)); }

  31. Das neue Modul für crosscutting concerns: aspect • AspectJ führt den aspect ein, eine logische Einheit vergleichbar mit einer Klasse, die pointcuts und advices enthält. publicaspect SimpleLogAspect { pointcut publicMethodExecution() : execution(* *.Module*.* (..)); pointcut privateMethodExecution() : execution(* *.Module*+.* (..)); before() : publicMethodExecution() { LogModule.logPublicMethodExecutionBegin(thisJoinPoint.getSignature().getName()); } before() : privateMethodExecution() { LogModule.logPrivateMethodExecutionBegin(“...”); } }

  32. Das neue Modul für crosscutting concerns: aspect • AspectJ führt den aspect ein, eine logische Einheit vergleichbar mit einer Klasse, die pointcuts und advices enthält. publicaspect SimpleLogAspect { pointcut publicMethodExecution() : execution(* *.Module*.* (..)); pointcut privateMethodExecution() : execution(* *.Module*+.* (..)); before() : publicMethodExecution() { LogModule.logPublicMethodExecutionBegin(thisJoinPoint.getSignature().getName()); } before() : privateMethodExecution() { LogModule.logPrivateMethodExecutionBegin(“...”); } after() : publicMethodExecution() { LogModule.logPublicMethodExecutionEnd(“...”); } after() : privateMethodExecution() { LogModule.logPrivateMethodExecutionEnd(“...”); } }

  33. Fragen?

  34. Wo sind wir? • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Aspect • Kontext von joinpoints

  35. Pointcut • Syntax • Operatoren in der pointcut-Definition • Unär: !pc für alle joinpoints außer denen, die durch pc gefangen werden • Binar: pc1 || pc2 für alle joinpoints, die entweder von pc1 oder von pc2 gefangen werden • Binär: pc1 && pc2 für alle joinpoints, die von pc1 und pc2 gefangen werden • Klammerung ist möglich [access specifier] pointcut name([args]) : pointcut-definition

  36. Signatur-Patterns • Um die joinpoints, die ein pointcut abfängt, effizient zu definieren, benutzt man folgende Signatur-Patterns, die im folgenden näher erläutert werden • Typ-Signatur für • Methoden-Signatur • Konstuktor-Signatur • Feld-Signatur

  37. Alle Typen, die Date heißen im Package java oder einem direkten Subpackage java.*.Date Ein beliebiger Typ in einem beliebigen Subpackage von java java..* javax.swing.*Model+ eine beliebige Unterklasse/Unterinterface, z.B. TableModel und TreeModel. Oder aber eine Klasse die das Interface implementiert z.B. DefaultTableModel Typ-Signatur-Pattern • für • den Typ eines Feldes • die Klasse einer Methode, die aufgerufen wird • die Argumente einer Methode • Exceptions, die geworfen werden

  38. public static void LogModule.log*() Typ-Signatur Methoden-Signatur-Pattern • für • den Aufruf einer Methode: call(<Methoden-Signatur-Pattern>) • die Ausführung einer Methode: execution(<Methoden-Signatur-Pattern>) • Es müssen die Modifier, der return-Typ, der Klassenname, der Methodenname und die Parametertypen angegeben werden. • Optional können auch die Typen der Exceptions, die geworfen werden angegeben werden * LogModule.*(..) throws IOException+ wirft IOException oder Unterklassen beliebige Modifier beliebige Argumente

  39. genau ein Parameter beliebigen Typs public Vector.new(*) Konstruktor-Signatur-Pattern • Werden wie Methoden-Signaturen verwendet. Nur ist der „Methoden“-Name immer new und es gibt keinen Rückgabewert Typ-Signatur-Pattern

  40. Feld-Signatur-Pattern public static int *Module*.answer Typ-Signatur-Pattern

  41. Überblick joinpoint-Typen • Diese pointcuts fangen jointpoints, die in einer bestimmten Situation auftreten

  42. Lexikalisch basierte pointcuts • Der lexikalische Sichtbarkeitsbereich ist ein Teil des Quellcodes wie die Definition einer Klasse oder einer Methode. • Diese pointcuts fangen alle jointpoints, die im lexikalischen Sichtbarkeitsbereich eines Typs liegen, unabhängig von der Situation (wie Methoden-Aufruf/-Ausführung usw.) within(Typ-Signatur) withincode(Methoden-Signatur)

  43. method1() print() Beispiel: joinpoint-Typen :Test :Module1 :Module2 print call print execution method1 call method1 execution main execution method1() method1 call && within(Module2) method1 execution

  44. cflow(pointcut) alle joinpoints inklusive denen aus pointcut cflowbelow(pointcut) alle joinpoints exklusive denen aus pointcut Controlflow basierte pointcuts • Weiterhin gibt es pointcuts, die alle joinpoints, die während der Ausführung von joinpoints, die von einem anderen pointcut abgefangen werden auftreten. Die joinpoints befinden sich im „control flow“ eines pointcuts

  45. Beispiel: Controlflow basierte pointcuts :Test :Module2 :Module1 method3() method1() print() cflow(call(* Module2.method3())) fängt alle joinpoints in diesem Bereich cflowbelow(call(* Module2.method3())) fängt alle joinpoints in diesem Bereich

  46. Wo sind wir? • Übersicht • Einführung in AOP • AOP mit AspectJ • Kurzübersicht AspectJ • Wie identifiziert AspectJ Stellen im Programmfluss? • Wie definiert man, was an diesen Stellen passiert? • Das neue Modul für crosscutting concerns: aspect • Vertiefung in AspectJ • Pointcut • Advice • Kontext von joinpoints • Aspect

  47. Advice • Ähnelt einer Java-Methode • Enthält Java-Code, der ausgeführt wird, wenn ein joinpoint abgefangen wird • Es gibt drei Typen • before • after • around

  48. before advice • Wird ausgeführt bevor der gefangene joinpoint ausgeführt wird. • Wird im advice body eine Exception geworfen, wird der joinpoint nicht ausgeführt. before() : executionOfMethod1() { doSomething(); } Wird hier eine Exception geworfen, wird method1 nicht ausgeführt

  49. wird immer ausgeführt after() : pointcut-spec wird nur ausgeführt, wenn die Methode erfolgreich war after() returning : pointcut-spec after() throwing : pointcut-spec wird nur geworfen, wenn die Methode eine Exception geworfen hat after advice • Es gibt drei Typen, die zwischen den Rückkehrmöglichkeiten der gefangenen Methode unterscheiden

  50. around advice • Wird um den joinpoint herum ausgeführt. Mit dem neuen Schlüsselwort proceed() wird die Ausführung des joinpoints veranlasst. Er hat einen Rückgabetyp, der dem der joinpoints entsprechen muss. void around() throws e: executionOfMethod1() { LogModule.logBegin(„…“); try { proceed(); } catch(Exception e) { LogModule.logExc(e); throw e; } LogModule.logEnd(„…“); }

More Related