Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt Seite: 2 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
I. Eidesstattliche Erklärung
(gemäß § 31, Abs. 7 RaPO)
Hiermit erkläre ich, dass ich die Arbeit selbstständig verfasst, noch nicht anderweitig für Prüfungszwecke vorgelegt, keine anderen als die angegebenen Quellen oder Hilfsmittel benutzt sowie wörtliche oder sinngemäße Zitate als solche gekennzeichnet habe.
Landshut, den 10.01.2005 ______________________________ (Eduard Hildebrandt)
Copyright © 2004 by Eduard Hildebrandt Seite: 3 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
II. Kurzfassung
Diese Diplomarbeit untersucht die Praxistauglichkeit der aspektorierten Programmierung (AOP) mit Java am Beispiel einer konkreten J2EE Anwendung. Nach einer kurzen Einführung in die Grundzüge der aspektorientierten Programmierung, werden die versichenenen Einsatzgebiete, wie Logging, Pooling, Qualitätssicherung oder Testen von Software vorgestellt. Dabei wird die AOP Lösung immer mit einer herkönlichen Java Implementierung vergliechen und die Vor- und Nachteile der beiden Implementierungen untersucht. Als Ergebnis dieser Arbeit soll geprüft werden, ob AOP inzwischen bereit für den Praxiseinsatz ist und der Nutzen sowie Probleme dieser Technologie untersucht werden.
Copyright © 2004 by Eduard Hildebrandt Seite: 4 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
III. Danksagung
Bei den meisten Diplomarbeiten steht auf der Titelseite in der Regel nur ein einziger Name als Autor der Arbeit. Dies ist eine arge Täuschung! Jede Diplomarbeit entsteht aus einer Kollaboration hingebungsvoller und talentierter Menschen. Beim Schreiben dieser Arbeit haben mir eine Vielzahl großzüger und kluger Leute mit Rat und Tat zur Seite gestanden. Besonderen tiefen Dank empfinde ich für:
Meine Eltern, denen diese Diplomarbeit gewidmet ist. Sie haben mir das Studium der Informatik überhaupt erst ermöglicht. Sie haben stets zu mir gehalten und mich immer unterstützt. Ich danke für ihre Liebe und Vertrauen. Sie sind die beiden Riesen, auf deren Schultern ich gestanden bin.
Frau Prof. Dr. Gudrun Schiedermeier, die mir meine erste Java Lektion während des Informatikstudiums gegeben hatte. Sie begleitete diese Diplomarbeit als Erstkorrektorin und gab mir die Freiheit ohne Zwänge und Auflagen eine neue Technologie zu erforschen. Stets war sie erreichbar und hatte immer gute Vorschläge, wie ich meine Arbeit verbessern kann. Dafür möchte mich herzlich bedanken.
Frau Prof. Dr. Monika Messerer, die mir die Themen Softwareengineering und Design Patterns im Laufe des Studiums beigebrachte hatte. Sie hat sich ebenfalls für diese Thematik als Zweitkorrektorin begeistern können.
Der Firma Kölsch & Altmann, wo ich die Möglichkeit hatte, meine Arbeit in einer sehr guten Arbeitsumgebung zu gestalten. Selten habe ich ein Unternehmen gesehen, in dem ein solch familiäres Arbeitsklima herrscht. Mein besonderer Dank gilt hier dem Geschäftsführer Dr. Werner Altmann, der mir diese Gelegenheit überhaupt erst ermöglichte und meine Arbeit stets mit großem Interesse verfolgte. Ein großer Dank gilt auch meinen beiden Betreuen Georg Süß und Klaus Dirlewanger, die mir immer mit Rat und Tat zur Seite gestanden haben.
Meinem besten Freund Matthias Schaufler, der immer für mich da ist. Er hat viel Zeit investiert diese Arbeit auf Rechtschreib- und Grammatikfehler zu überprüfen. Für seine Mühen möchte ich mich besonders bedanken, da er sich eigentlich nicht für Informatik interessiert und daher auch relativ wenig vom Inhalt verstanden hat. Umso mehr konnte er durch seine Vorschläge die Ausdrucksweise verbessern.
Meine Studienkollegien Waldemar Mertke und Philipp Morgenthaler, die sich die Zeit genommen haben, meine Diplomarbeit durchzulesen und viel konstruktive Kritik gegeben haben.
Allen anderen Leuten, die ich hier nicht explizit erwähnt habe, die jedoch in vielen verschiedenen Dialogen durch Ihre Ansichten und Vorschläge ebenfalls zum Erfolg dieser Arbeit beigetragen haben.
Copyright © 2004 by Eduard Hildebrandt Seite: 5 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
IV. Inhaltsverzeichnis
I. Eidesstattliche Erklärung 3
II. Kurzfassung 4
III. Danksagung 5
IV. Inhaltsverzeichnis 6
VI. Abbildungsverzeichnis 8
Kapitel 1: Einführung 9
1.1 Einleitung 9
1.2 Ziel der Arbeit 10
1.3 Voraussetzungen 10
1.4 Motivation 10
1.5 Aspektorientierte Programmierung 12
1.6 Weben von Aspekten 14
1.6.1 statisches Weben 14
1.6.7 dynamisches Weben 14
1.7. AspectJ 14
1.7.1 Schnittpunkte (engl. pointcuts) 15
1.7.2 Advices 16
1.7.3 Aspekte 16
1.7.4 Introductions 17
1.7.5 Compiler Regeln 17
1.8. „Hello World“ mit AspectJ 18
1.9. Zusammenfassung 19
Kapitel 2: Die Anwengung iPad 21
2.1 Anforderungen 21
2.2 Design 23
2.2.1 Klassen Design 23
2.2.2 Datenbank Design 23
2.2.3 Grafische Oberfläche 24
2.2.4 Architektur 25
2.3 Implementierung 27
2.3.1 Allgemeines 27
2.3.2 Technologien 27
2.3.2.1 Hibernate 27
2.3.2.2 Axis 28
2.3.2.3 Lucene 28
2.3.2.4 Eclipse RCP 29
2.3.2.5 JDIC 31
2.3.3 Probleme und Erfahrungen 31
2.3.3.1 SWT 31
2.3.3.1 Performance 32
2.4 Bewertung des Designs und Architektur 32
2.5 Zusammenfassung 33
Kapitel 3: Tracing und Logging 34
3.1 Konventionelles Logging 34
3.2 Logging mit AspectJ 36
3.2.1 Protokollieren von Methodenaufrufen 36
3.2.2 Protokollieren von Feldzugriffen 39
3.2.3 Protokollieren von Exceptions 40
3.3 Spezielle Logging Anwendungen 42
3.3.1 Protokollieren von SQL Statements 42
3.3.2 Protokollieren von Sessions 42
3.3.3 Protokollieren von Webservice Requests 43
3.4 Einsatz in der Beispielanwendung 44
3.5 Zusammenfassung 44
Copyright 2004 by Eduard Hildebrandt Seite: 6 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Kapitel 4: Qualitätssicherung 45
4.1 Best-Practices Richtlinien 45
4.2 EJB Richtlinien 46
4.3 Swing Richtlinien 47
4.4 Architektur Richtlinien 48
4.5 Benutzerdefinierte Richtlinien 49
4.6 Richtlinien für Namenskonventionen 50
4.7 Weitere Tools 51
4.8 Einsatz in der Beispielanwendung 51
4.9 Zusammenfassung 52
Kapitel 5: Pooling und Caching 53
5.1 Thread Pool 54
5.1.1 Java Implementierung 54
5.1.2 AspectJ Implementierung 56
5.1.3 Bewertung 57
5.2 XSLT Cache 58
5.2.1 Java Implementierung 58
5.2.2 AspectJ Implementierung 60
5.2.3 Bewertung 60
5.3 Einsatz in der Beispielanwendung 61
Kapitel 6: Design Patterns 62
6.1 Singleton Pattern 62
6.1.1 Java Implementierung 62
6.1.2 AspectJ Implementierung 62
6.1.3 Bewertung 64
6.2 Observer Pattern 64
6.2.1 Java Implementierung 65
6.2.2 AspectJ Implementierung 65
6.2.3 Bewertung 67
6.3 Zusammenfassung 67
Kapitel 7: Testen mit AspectJ 68
7.1 Prüfungen privater Variablen 68
7.2 Austausch von Methoden und Objekten 69
7.3 Virtuelle Mock Objekte 70
7.4 Unit Test Coverage 71
Kapitel 8: Fazit 73
8.1 Bewertung der Technologie 73
8.3 Ausblick in die Zukunft 74
8.4 Zusammenfassung 75
VII. Literaturverzeichnis 76
VIII. Abkürzungsverzeichnis 78
IX. Glossar 79
X. Anhänge 84
Anhang A: Eingesetzte Hilfsmittel 84
Anhang B: Inhalt der CD-ROM nicht enthalten
Anhang :D Java AOP Implementierungen 87
Anhang E: AspectJ Plugins für Entwicklungsumgebungen 88
Copyright 2004 by Eduard Hildebrandt Seite: 7 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
VI. Abbildungsverzeichnis
Abbildung 1: Parsen einer XML Datei 10
Abbildung 2: Logging 11
Abbildung 3: Quellcode der Klasse Konto 11
Abbildung 4: Quellcode der Klasse Konto incl. technischer Belange 12
Abbildung 5: Weben von Aspekten 13
Abbildung 6: AOP als Lichtstrahl 13
Abbildung 7: Use-Case Diagram Resource-Management System 21
Abbildung 8: Klassendiagramm mit zentralen Klassen der Anwendung 23
Abbildung 9: Datenbank Design der Anwendung 24
Abbildung 10: Paper Prototyp der Benutzeroberfläche 24
Abbildung 11: Screenshot der Benutzeroberfläche 25
Abbildung 12: Architektur Übersicht 26
Abbildung 13: Eclipse IDE 30
Abbildung 14: Eclipse Architektur 30
Abbildung 15: AspectJ Laufzeit-Bibliothek 38
Abbildung 16: Vier Schichten Architektur 48
Abbildung 17: Sequenzdiagramm Erzeugung und Benutzung von Ressourcen 53
Abbildung 18: Sequenzdiagram Verwendung eines Pools 54
Abbildung 19: Klassendiagramm Singleton Pattern 62
Abbildung 20: Klassendiagram für Grafikprogramm 64
Abbildung 21: UML Diagramm für Mock Klassen 70
Abbildung 22: Downloads von AspectJ 74
Copyright 2004 by Eduard Hildebrandt Seite: 8 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Kapitel 1: Einführung
1.1 Einleitung
Der Mensch hätte nur selten Großes erreicht, wenn er alle Frustrationen hinnehmen würde. Treibt doch die Frage „Muss es so sein?“ unseren Erfindungsgeist an. Hieraus erwachsen politische Reformen und wissenschaftliche Erneuerungen. Die Römer mochten Frustrationen nirgendwo hinnehmen. Sie gingen nicht gerne auf schlammigen Straßen, also pflasterten sie diese. Sie verabscheuten die winterliche Kälte und ersannen so die Fußbodenheizung.
Nicht anderes verhält es sich mit dem Prozess der Softwareentwicklung. Die Unzufriedenheit der Programmierer treibt diese dazu, immer wieder neuere und effizientere Wege bei der Softwareentwicklung zu beschreiten.
In den frühen Tagen der Informatik haben die Entwickler ihre Programme direkt in Form von Maschinen-Befehlen eingegeben. Leider verbrachten die Programmierer mehr Zeit damit, über den Befehlsatz für den jeweiligen Prozessor, als über das eigentliche Problem nachzudenken. So entstanden die ersten höheren Programmiersprachen, die eine Abstraktion der zugrunde liegenden Maschine erlaubten.
Mit der Zeit kamen die prozeduralen Sprachen und ermöglichten es, die Probleme in kleinere Teilprobleme zu zerlegen und diese in Prozeduren abzubilden. Da die Komplexität der Programme jedoch ständig anwuchs, wurde bald eine ausgefeiltere Technik benötigt.
Während bei prozeduralen Programmiersprachen die Daten und Prozeduren getrennt betrachtet wurden, werden diese in der objektorientierten Programmierung zu einer Einheit in Form von Objekten zusammengefasst. Die objektorientierte Programmierung (OOP) betrachtet ein System als eine Menge von Objekten, die untereinander interagieren. Abstraktion, Kapselung, Vererbung und Polymorphie sind die grundlegenden Prinzipien der OOP. Dieser Programmierstil bietet softwaretechnisch gegenüber anderen älteren Verfahren große Vorteile, da hiermit eine wesentlich natürlichere Modellierung ermöglicht wird und große Systeme leichter verwaltet werden können.
Programmierparadigmen und –sprachen definieren die Art und Weise, wie wir uns mit Maschinen verständigen. Jede neue Methode präsentiert einen anderen Weg die realen Objekte der Welt - auf eine für uns Menschen natürlichere Art - in Datenkonstrukte auf dem Rechner abzubilden. Die Evolution der Programmiermethoden ermöglicht es uns immer bessere und komplexere Softwaresysteme zu bauen.
Zum Zeitpunkt der Erstellung dieser Arbeit ist OOP die am weitesten verbreitete Methodenlehre. In der Tat hat OOP seine Stärken beim Modellieren von allgemeinen Verhalten gezeigt. Ein Bankkonto, auf dem man einen Betrag einzahlen oder abheben kann, lässt sich mit OOP sehr leicht und elegant modellieren.
In der Praxis zeigt sich jedoch, dass es beim Entwurf eines Softwaresystems viele technische Anforderungen, wie z.B. Logging, Persistenz oder Authentifizierung gibt, die sich nicht klar auf eine funktionale Einheit beschränken lassen. Sie durchdringen das gesamte System und lassen sich nur sehr schwer und umständlich in Form von Klassen kapseln. Solche Anforderungen werden auch als „querschneidende Anforderungen“ oder „cross-cutting concerns“ bezeichnet.
Durch ausschließlich funktionale Dekomposition und Refaktorisierung ist es nur in wenigen Fällen möglich, solche Anforderungen unabhängig voneinander und vom Gesamtsystem mit reiner OOP zu modellieren. Beispielsweise ist es nicht möglich den Zugriff auf das Objekt Konto zu protokollieren, ohne die Struktur der Klasse zu verändern. Hier liegen die Grenzen von objektorientierter Programmierung.
Copyright © 2004 by Eduard Hildebrandt Seite: 9 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Genau hier versucht die aspektorientierte Programmierung (AOP) Abhilfe zu leisten. Ziel der Aspektorientierten Programmierung ist es querschneidende Anforderungen in Form von Aspekten zu kapseln und die Komponenten des Systems von ihnen frei zu halten.
AOP könnte der nächste große Schritt in der Entwicklung der Programmiermethoden sein.
1.2 Ziel der Arbeit
Mit dieser Diplomarbeit soll die Praxistauglichkeit dieser neuen Technologie am Beispiel einer J2EE Anwendung evaluiert werden.
Es sei darauf hingewiesen, dass diese Arbeit keine vollständige Beschreibung der AspectJ-Sprache darstellen soll. Auch wenn eine ausführliche, deutschsprachige Dokumentation für AspectJ noch fehlt, ist es nicht Ziel dieser Arbeit eine solche zu erstellen. Der Autor erklärt zwar alle wichtigen Sprachelemente von AspectJ, für die Programmierung mit AspectJ ist jedoch ein Studium der Dokumentation [AJDOC] oder der im Anhang C vorgeschlagenen Literatur unumgänglich.
Es ist auch nicht Thema dieser Arbeit ist, das Design und die Architektur der Anwendung zu beschreiben. Aus diesem Grund beleuchtet das zweite Kapitel nur die wichtigsten Design- und Architekturentscheidungen und soll keine vollständige Dokumentation darstellen. Auch wenn viele Konzepte der Anwendung aus der Sicht eines Software-Architekten sehr interessant sind, wurde auf eine ausführliche Beschreibung dieser Konzepte zu Gunsten von AOP Themen verzichtet.
1.3 Voraussetzungen
Bei dieser Diplomarbeit werden Kenntnisse in der Modellierung und Implementierung von objektorientierten Softwaresystemen vorausgesetzt. Außerdem sind Programmierkenntnisse in Java sowie ein Grundverständnis der Java 2 Platform Enterprise Edition (J2EE) notwendig. Praktische Erfahrungen auf diesem Gebiet sind, zum Verständnis von großem Vorteil.
1.4 Motivation
Anforderungen, wie z.B. das Parsen einer XML Datei, lassen sich mit OOP relativ einfach implementieren. Die Grafik in der Abbildung 1 visualisiert den Quellcode von Apache Tomcat.
Jeder Balken repräsentiert eine Klasse. Der Quellcode, welcher zum Parsen einer XML Datei notwendig ist, wurde in der Grafik hervorgehoben dargestellt. Wie man der Grafik entnehmen kann, ist der Code innerhalb einer einzigen Klasse gekapselt. Dies macht es einfach, den Code zu modifizieren und wieder zu verwenden.
Copyright © 2004 by Eduard Hildebrandt Seite: 10 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Betrachten wir nun eine Anforderung wie z.B. Logging: Abbildung 2 visualisiert auf dieselbe Art und Weise den Quellcode von Apache Tomcat. Der hervorgehobene Quellcode ist für das Logging innerhalb der Anwendung zuständig.
Wie wir an der Grafik erkennen können, ist der Quellcode über das gesamte System verstreut. Anforderungen dieser Art werden auch als „querschneidende Anforderungen“ oder „crosscutting concerns“ bezeichnet. Sie durchdringen das gesamte System und machen es notwendig, dass das System an mehreren Stellen verändert werden muss.
Möchte man z.B. auf ein anderes Logging Framework umsteigen, so müssen alle betroffenen Codestellen gefunden werden und es muss sichergestellt werden, dass alle Änderungen konsistent durchgeführt werden. Die Modifizierung der Anwendung ist also relativ aufwendig. Eine solche Implementierung kann auch kaum wieder verwendet werden.
Betrachten wir ein weiteres Beispiel für querschneidende Anforderungen: In einer einfachen Bankanwendung würde die Klasse Konto Variablen für Kontonummer und Guthaben enthalten. Weiterhin würde die Klasse neben Getter- und Setter-Methoden auch Methoden für Ein- und Auszahlungen implementieren. Die Abbildung 3 zeigt den Quellcode für unsere vereinfachte Darstellung der Java Klasse Konto.
Der Quellcode ist sehr einfach zu lesen und leicht zu verstehen. Die Geschäftslogik der Klasse ist auf den ersten Blick verständlich. Reale Systeme bestehen jedoch nicht nur aus reiner Geschäftslogik, sondern müssen auch jede Menge technische Belange, wie z.B. Logging, Authentifizierung oder Synchronisierung implementieren.
Copyright © 2004 by Eduard Hildebrandt Seite: 11 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Die Abbildung 4 stellt den Quellcode derselben Klasse
Konto
dar. Diesmal sind jedoch auch Logging, Authentifizierung und Synchronisierung implementiert worden.
Abbildung 4: Quellcode der Klasse Konto incl. technischer Belange
Der Quellcode der Klasse ist nun wesentlich schwerer zu überblicken. Verschiedene technische Belange sind jetzt mit der Geschäftslogik eng vermischt. Der Quellcode hat eine hohe Redundanz und es besteht eine starke Kopplung zwischen den Klassen. Bedenkt man, dass es in einem echten System in der Regel bedeutend mehr technische Anforderungen, wie z.B. Persistenz, Transaktionen oder Validierung gibt, so würde die Implementierung noch wesentlich komplexer werden.
Hier zeigt sich die Schwäche von OOP. Es ist sehr schwierig, querschneidende Anforderungen modular zu implementieren. Aspektorientierte Programmierung (AOP) versucht an dieser Stelle Hilfestellung zu leisten, indem es solche Anforderungen unabhängig vom Quellcode in Form von Aspekten kapselt.
1.5 Aspektorientierte Programmierung
Aspektorientierte Programmierung (AOP) ist ein Programmierparadigma für das Design und die Implementierung von Softwaresystemen. Es handelt sich um ein neues Konzept zur orthogonalen Programmierung. Dabei werden technische Anforderungen (wie z.B. Logging oder Persistenz) in so genannten Aspekten gekapselt. Es erfolgt eine logische und physische Trennung der Programmlogik für verschiedene Anforderungen. Diese unabhängigen Programmstücke werden dann von einem speziellen Compiler zu einem kompletten System kompiliert. Man sagt auch, dass die Programmstücke von einem Weber („Weaver“) zu einem System verwoben werden. Die Abbildung 5 visualisiert diesen Vorgang.
Copyright © 2004 by Eduard Hildebrandt Seite: 12 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Bildlich kann AOP mit einem Lichtstrahl und zwei Prismen verglichen werden. Wie auf der Abbildung 6 dargestellt, existieren zu Beginn die Anforderungen, die ein Kunde an ein System hat. Aufgabe des Designers ist es, die Anforderungen in verschiedene Aspekte zu trennen, damit diese getrennt implementiert werden können. Der Weber verwebt schließlich alle Aspekte mit der eigentlichen Geschäftslogik zu einem vollständigen System.
Mit AOP ist es möglich, an einer zentralen Stelle festzulegen, dass alle Methoden, die bestimmten Bedingungen genügen, bei ihrem Aufruf eine bestimmte Aktion durchführen. Es ist z.B. möglich festzulegen, dass bei jedem Methodenaufruf in der Klasse Konto ein entsprechender Eintrag in die Log-Datei geschrieben wird. Ohne AOP müsste die Schreiboperation gesondert in jede Methode eingefügt werden.
Ziel der AOP ist die logische und physikalische Trennung der Geschäftslogik von den technischen Details. Dabei erhebt AOP nicht den Anspruch objektorientierte Paradigmen zu ersetzen, sondern ergänzt diese, um eine bessere Modularität und Wiederverwendbarkeit zu erreichen, die in dieser Form mit reiner OOP nicht möglich wäre. AOP verbessert die Lesbarkeit und Verständlichkeit des Quellcodes und ermöglich somit eine leichtere Wartung des Systems.
1 Quelle: http://www.javaworld.com/javaworld/jw-01-2002/jw-0118-aspect_p.html
Copyright © 2004 by Eduard Hildebrandt Seite: 13 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
1.6 Weben von Aspekten
Das Kombinieren der Aspekte mit dem restlichen Programmcode wird auch „Weben“ genannt. Der dafür eingesetzte Compiler wird auch als „Aspektweber“ bezeichnet. Dabei wird grundsätzlich zwischen statischem und dynamischem Weben unterschieden:
1.6.1 statisches Weben
Beim statischen Weben wird der Aspektcode während der Kompilierung fest mit dem übrigen Programmcode verbunden. Dies kann z.B. durch Präprozessoren erfolgen. Dabei werden die Aspekte in traditionelle Programmierkonstrukte umgeformt. Der Vorteil dieser Technik ist die einfache Implementierung, da die bestehenden Compiler ohne große Änderungen weiterbenutzt werden können. Nachteilig an dieser Lösung ist jedoch die fehlende Integration in die Programmiersprache. Nach dem Kompilieren sind alle Informationen über Aspekte im Quellcode verloren und können nicht für Fehlermeldungen verwendet werden. Dies erschwert das Debugging und beinträchtigt den Entwicklungskomfort erheblich.
Eine Alternative zu Präprozessoren ist die Verwendung einer eigenen Sprache oder die Erweiterung einer bereits existierenden Sprache. Durch die direkte Integration der Aspekte in die Programmiersprache können die Fehlermeldungen beim Debugging speziell auf die Gegebenheiten der Aspekte zugeschnitten werden.
1.6.7 dynamisches Weben
Vom dynamischen Weben der Aspekte spricht man, wenn das eigentliche Weben zur Laufzeit der Anwendung geschieht. Dynamisches Weben erhöht die Flexibilität einer Anwendung, da das Verhalten des Programms zu Laufzeit dynamisch angepasst werden kann. Diese Flexibilität wird jedoch mit dem Preis von höherem Speicherverbrauch und schlechterem Laufzeitverhalten erkauft.
Zusammenfassend kann man sagen, dass statisches Weben Vorteile durch Optimierung während des Kompiliervorgangs bringt, während dynamisches Weben zur Laufzeit auf Veränderungen reagieren und das Programmverhalten anpassen kann.
1.7. AspectJ
AspectJ [AJHP] ist eine AOP Spracherweiterung für Java. AspectJ wurde selbst ebenfalls in Java implementiert und stellt momentan die wohl bekannteste und umfangreichste AOP Erweiterung für Java dar. Ursprünglich wurde AspectJ von Xerox im Palo Alto Research Center (Xerox PARC) [PARCHP] entwickelt. In der Zwischenzeit ist AspectJ ein Teilprojekt der Eclipse [ECHP] Entwicklungsumgebung und ist unter der Common Public License (CPL) [WCPL] komplett im Quellcode verfügbar. AspectJ erfreut sich einer sehr großen, aktiven Gemeinde und wurde auch bereits in vielen umfangreichen kommerziellen Projekten eingesetzt. Aufgrund der starken Verbreitung und des beträchtlichen Funktionsumfangs wurde beschlossen, AspectJ auch im Rahmen dieser Diplomarbeit als aspektorientierte Spracherweiterung einzusetzen. Eine Liste weiterer AOP Implementierungen für Java befindet sich im Anhang C.
AspectJ verwendet statisches Weben. Es handelt sich um eine eigenständige Sprache mit einem eigenen Compiler, welcher allerdings standardkonformen Java-Bytecode produziert. Dies hat den Vorteil, dass die bestehende Infrastruktur von Java weiter genutzt werden kann.
AspectJ erweitert Java um fünf „kleine“ Sprachelemente:
• pointcut
• advice
• aspect
• introduction
• compiler rule
Im Folgenden werden diese Sprachelemente etwas genauer betrachtet:
Copyright © 2004 by Eduard Hildebrandt Seite: 14 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
1.7.1 Schnittpunkte (engl. pointcuts)
Webepunkte, auch „join points“ genannt, sind eindeutige Punkte im Programmablauf, an denen durch den Compiler zusätzliche Anweisungen eingefügt werden können. Ein Webepunkt könnte ein Methoden- oder Konstruktoraufruf, der Zugriff auf eine Variable oder die Initialisierung einer Klasse sein.
Mehrere Webepunkte werden zu so genannten Schnittpunkten, im Englischen auch „pointcuts“ genannt, zusammengefasst. Schnittpunkte selektieren mit einer Art Abfragesprache eine Menge von Webepunkten. Ein Beispiel für solch eine Auswahl von Webepunkte wäre: „Alle Variablenzugriffe in allen Klassen, die mit ‚EJB’ enden, jedoch nicht im Package com.mybank.konto.“
Die Syntax für die Definition eines Poincuts in AspectJ lautet:
[abstract] [Modifikator] pointcut Bezeichnung ([Parameter]) : Pointcut-Typ;
Mögliche Pointcut Typen in AspectJ sind das Aufrufen oder Ausführen einer Methode (call, execution), der Zugriff auf Variablen (get, set), Ausnahmebehandlung (handler), das Ausführen von Aspektcode (adviceexecution) oder die Initialisierung von Klassen und Variablen (staticinitialization, initialization, preinitialization). Weiterhin existieren so genannte strukturbasierte Pointcuts, mit denen es möglich ist, bestimmte Bereiche auszuwählen, wie z.B. den Code innerhalb eines bestimmten Typs bzw. einer Klasse (within, withincode) oder innerhalb eines Schnittpunktes (cflow, cflowbelow). Auch ist es möglich, den Typ der Klassen oder Methodenparameter (this, target, args) zu bestimmen.
Betrachten wir einige Beispiele für Pointcuts:
public pointcut loggingMethods() :
call(void Konto.einzahlen(int));
Dieses Beispiel definiert einen öffentlichen
Pointcut mit dem Namen loggingMethods, welcher jedes Mal beim Aufruf der Methoden einzahlen der Klasse Konto zutrifft.
Bei der Definition von Poincuts ist es möglich,
Wildcards zu verwenden:
private pointcut toStringMethods() :
execution(* *.toString*(..));
In diesem Fall wird ein privater Pointcut mit dem
Namen toStringMethods definiert, der bei der Ausführung aller Methoden, die mit “toString” beginnen, aktiv wird. Dabei ist es egal, in welcher Klasse die Methode enthalten ist, welchen Rückgabewert diese hat oder welche Parameter übergeben werden.
Weiterhin besteht die Möglichkeit, Pointcuts mit Hilfe von logischen Operatoren zu kombinieren. Möchte man z.B. erreichen, dass ein Pointcut bei allen Schreibzugriffen auf Variablen, deren Namen nicht mit „m“ oder „l“ beginnen, aktiv wird und der Pointcut gleichzeitig aber nur bei Zugriffen innerhalb der Klasse „Konto“ aktiv werden soll, so würde der Pointcut folgendermaßen lauten:
public pointcut memberAccess() : set(*) && (!set(m*) || !set(l*)) && within(Konto);
Pointcuts selektieren also eine Menge von Zeitpunkten oder Ereignissen im Ablauf eines Programms.
Copyright © 2004 by Eduard Hildebrandt Seite: 15 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
1.7.2 Advices
Mit Empfehlungen bzw. „advices“ ist es möglich, die Ausführung von bestimmten Aktionen zu definieren, wenn ein gewisser Pointcut erreicht wird. In AspectJ werden solche Aktionen in Form von normalem Java Code innerhalb eines Advice Blocks definiert. Je nach Typ des Advices wird die Aktion dann vor dem Erreichen (before) des Pointcuts, nach dem Ausführen (after) des Pointcuts oder statt der Ausführung (around) des Pointcuts ausgeführt.
Die Syntax für die Definition eines Advices in AspectJ lautet:
before ([Parameter]) : Pointcut { Aktion } after ([Parameter]) : Pointcut { Aktion } after ([Parameter]) returning [(Parameter)] : Pointcut { Aktion } after ([Parameter]) throwing [(Parameter)] : Pointcut { Aktion } Typ around ([Parameter]) : Pointcut { Aktion }
Einige Beispiele:
before(int i) : set(int Konto.kontostand) && args(i) { ... }
Die Anweisungen im Körper werden ausgeführt, bevor ein Schreibzugriff auf die Variable kontostand in der Klasse Konto stattfindet. Innerhalb des Körpers kann man auf den neuen Wert der Variable über den Variablennamen „i“ zugreifen.
after(int x) returning(): call(void Konto.abheben(int)) && args(x) { ... };
Der Körper wird nach der erfolgreichen Ausführung (returning) der Methode abheben() ausgeführt. Der übergebene Parameter steht innerhalb des Körpers unter der Variable „x“ zur Verfügung.
after() throwing(LimitException e) : call(void Konto.abheben(int)) { ... };
Der Advice wird nur nach dem Werfen (throwing) einer LimitException ausgeführt. Die Exception bekommt im Körper den Variablennamen „e“.
int around() : call(int Konto.getKontostand()) {…}
In diesem Fall wird der Körper an Stelle der Methode getKontostand() ausgeführt. Im Körper gibt es jedoch die Möglichkeit, die Methode getKontostand() dennoch auszuführen. Dafür dient die Methode proceed(). Siehe dazu auch Kapitel 3.2.1.
1.7.3 Aspekte
Vergleichbar mit Klassen in Java können Aspekte Variablen und Methoden enthalten oder Eigenschaften von anderen Klassen und Aspekten erben und Interfaces implementieren. Darüber hinaus bieten Aspekte allerdings noch erweiterte Funktionalität und dienen als Container für Pointcuts und Advices.
Die Syntax für die Definition eines Advices in AspectJ lautet:
[privileged][Modifikator] aspect Bezeichnung
[extends
Typ]
[implements
Typ-Liste]
[perKlausel] {
Körper
}
Ein Beispiel: public aspect A extends B implements I, J {
private pointcut loggingMethods() : ...;
before() : loggingMethods() { ... } }
Copyright © 2004 by Eduard Hildebrandt Seite: 16 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Das oben gezeigte Beispiel implementiert einen Aspekt „A“, welcher sich von einem anderen Aspekt oder der Klasse „B“ ableitet sowie zusätzlich die Interfaces „I“ und „J“ implementiert. Weiterhin enthält der Aspekt einen Pointcut loggingMethods und einen before-Advice.
1.7.4 Introductions
Introductions können bestehende Klassenstrukturen verändern. Das heißt, es können neue Attribute und Methoden hinzugefügt werden oder neue Schnittstellen implementiert (declare parents) werden. Außerdem können Exceptions abgeschwächt werden (declare soft), so dass diese nicht mehr explizit abgefangen werden müssen.
Die Syntax für Introductions lautet:
declare parents : Typ extends Typ
declare parents : Typ implements Typ-Liste declare soft : Typ : Pointcut Ein Beispiel:
001 public interface Nameable {
002 public String getName();
003 public void setName(String name);
004 }
001 public aspect NameableManagement { 002 declare parents : Resource implements Nameable; 003 private String Resource.name;
004 public String Resource.getName() { 005 return this.name;
006 } 007 public void Resource.setName(String name) { 008 this.name = name;
009 } 010 } In diesem Beispiel sorgt der Aspekt NameableManagement dafür, dass die Klasse Resource zusätzlich das Interface Nameable implementiert und die Klasse um die notwendigen Methoden erweitert.
1.7.5 Compiler Regeln
Des Weiteren bietet AspectJ die Möglichkeit, den Compiler durch zusätzliche Regeln intelligenter zu gestalten. Mit Hilfe von declare error bzw. declare warning ist es möglich, beim Aufruf von einem bestimmten Pointcut eine Warnung auszugeben oder den Kompilationsvorgang ganz abzubrechen. Die genaue Syntax lautet:
declare error : Pointcut : String declare warning : Pointcut : String Auch dazu einige Beispiele:
Möchte man z.B. erreichen, dass die Programmierer nicht System.out.println() für Debug-Meldungen verwenden sondern das neu eingeführte Logging Framework einsetzen, so lässt sich dies mit den folgenden Codezeilen erreichen:
declare warning : get(* System.out) || get(* System.err) : “Verwenden Sie bitte die Logging API!"; In diesem Fall wird beim Kompilieren des Quellcodes jedes Mal, wenn auf System.out oder System.err zugegriffen wird, eine entsprechende Warnung ausgegeben.
Copyright © 2004 by Eduard Hildebrandt Seite: 17 von 88
Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Hat man eine Richtlinie festgelegt, wonach das Abspeichern von Daten in die Datenbank nur mit Hilfe eines Framework zu verrichten ist und der Zugriff auf die Datenbank aus anderen Klassen nicht erlaubt sein darf, so kann man dies mit relativ wenig Aufwand ständig vom Compiler überprüfen lassen.
declare error : call(* java*.sql.*.*(..)) && !(withhin(de.ka-muc.sqladapter.*) : „JDBC Klassen dürfen nicht direkt benutzt werden!“;
In diesem Fall gibt der Compiler nicht nur eine Warnung aus, sondern bricht den Kompilationsvorgang beim Zugriff auf die SQL Klassen außerhalb des Frameworks komplett ab und zeigt eine entsprechende Fehlermeldungen an.
1.8. „Hello World“ mit AspectJ
Im Folgenden werden die im Kapitel 1.7 vorgestellten Sprachkonstrukte noch einmal an einem kleinen Beispiel erläutert. Um dieses und alle folgenden Beispiele nachvollziehen zu können, benötigt man eine einsatzfähige AOP-Entwicklungsumgebung. Alle dafür notwendigen Schritte sind in der AspectJ Dokumentation im „Development Environment Guide“ erläutert. [AJDEV] Als Ausgangspunkt für unser Beispiel verwenden wir ein einfaches „Hello World!“ Programm.
001 public class HelloWorld {
002 public void sayHello(String name) { 003 System.out.println("Hello " + name + "!"); 004 } 005 public static void main(String[] args) { 006 HelloWorld helloWorld = new HelloWorld(); 007 helloWorld.sayHello("World");
008 } 009 }
Dieses einfache Programm gibt nur „Hello World!“ auf der Konsole aus:
> java HelloWorld
Hello World!
Erweitern wir nun das Programm um einen Aspekt:
001 public aspect HelloWorldAspect { 002 private pointcut sayHelloMethod() : 003 execution(void HelloWorld.sayHello(String)); 004 before() : sayHelloMethod() { 005 System.out.println("Before Advice!"); 006 } 007 }
Dieser Aspekt veranlasst das Programm vor der Ausführung der Methode sayHello(String) die Meldung „Before Advice!“ auszugeben.
> java HelloWorld
Before Advice!
Hello World!
Was ist hier passiert? Dekompilieren wir einfach das Programm und betrachten wir, was der Compiler in diesem Fall gemacht hat.
001 public class HelloWorld {
002 public void sayHello(String name){ 003 HelloWorldAspect.aspectOf().ajc$before$HelloWordAspect$1$53011669(); 004 System.out.println("Hello " + name + "!"); 005 }
Quote paper:
Eduard Hildebrandt, 2005, Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung, Munich, GRIN Publishing GmbH
This text can be quoted and accessed from this url:
Embed
DOI
Formatvorlage (Microsoft Word) für eine Diplomarbeit, Masterarbeit, Ha...
Für MS Word 2003 - Update 2010
Presentations, Models, Tutorials, Instructions
Elaboration, 25 Pages
Formatvorlage (OpenOffice) für eine Diplomarbeit, Masterarbeit, Hausar...
Presentations, Models, Tutorials, Instructions
Elaboration, 35 Pages
Formatvorlage / Vorlage zur Erstellung einer Diplomarbeit, Bachelorarb...
Presentations, Models, Tutorials, Instructions
Elaboration, 15 Pages
Formatvorlage / Vorlage für eine Diplomarbeit / Hausarbeit
Für MS Word 2007 - dotx
Presentations, Models, Tutorials, Instructions
Elaboration, 25 Pages
Anleitung zum Erstellen schriftlicher Arbeiten: Der Aufbau einer wisse...
Presentations, Models, Tutorials, Instructions
Elaboration, 20 Pages
Erstellen einer schriftlichen Hausarbeit
Presentations, Models, Tutorials, Instructions
Termpaper, 14 Pages
Grundtechniken wissenschaftlichen Arbeitens
Bibliografieren - Reden - Schr...
Presentations, Models, Tutorials, Instructions
Script, 46 Pages
Ratgeber zur Erstellung wissenschaftlicher Arbeiten. Diplomarbeiten - ...
Presentations, Models, Tutorials, Instructions
Elaboration, 39 Pages
Eduard Hildebrandt has published the text Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung
Eduard Hildebrandt has uploaded a new text
Parallele Programmierung spielend gelernt mit dem Java-Hamster-Modell
Programmierung mit Java-Thread...
Dietrich Boles
Scientific Engineering of Distributed Java Applications.
Third International Workshop, ...
Egidio Astesiano, Gianna Reggio, Nicoals Guelfi
Scientific Engineering for Distributed Java Applications
International Workshop, FIDJI ...
Nicolas Guelfi, Egidio Astesiano, Gianna Reggio
0 comments