Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung


Diplomarbeit, 2005
88 Seiten, Note: 1

Leseprobe

FACHHOCHSCHULE LANDSHUT
Fachbereich Informatik
Aspektorientierte Programmierung mit Java
gezeigt am Beispiel einer konkreten Anwendung
Diplomarbeit
zur Erlangung des Grades eines
Diplom Informatikers (FH)
erstellt von
Eduard Hildebrandt
Eingereicht: 10. Januar 2005

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 2 von 88
Widmung
Diese Diplomarbeit ist meinen Eltern gewidmet,
die immer für mich da sind.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 3 von 88
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)

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 4 von 88
II. Kurzfassung
Diese Diplomarbeit untersucht die Praxistauglichkeit der aspektorie
ntierten Programmierung (AOP)
mit Java am Beispiel einer konkreten J2EE Anwendung. Nach einer kurzen Einführung in die
Grundzüge der aspektorientierten Programmierung, werden die versch
iedenen Einsatzgebiete,
wie Logging, Pooling, Qualitätssicherung oder Testen von Software vorgestellt. Dabei wird die
AOP Lösung immer mit einer herkö
mmlichen Java Implementierung verglichen 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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 5 von 88
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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 6 von 88
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.
2 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

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 7 von 88
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 ...85
Anhang D: Java AOP Implementierungen ...87
Anhang E: AspectJ Plugins für Entwicklungsumgebungen ...88

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 8 von 88
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

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 9 von 88
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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 10 von 88
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.
Abbildung 1: Parsen einer XML Datei

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 11 von 88
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.
Abbildung 2: Logging
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 ,,cross-
cutting 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.
Abbildung 3: Quellcode der 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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 12 von 88
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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 13 von 88
Abbildung 5: Weben von Aspekten
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.
Abbildung 6: AOP als Lichtstrahl
1
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

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 14 von 88
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:
x
pointcut
x
advice
x
aspect
x
introduction
x
compiler rule
Im Folgenden werden diese Sprachelemente etwas genauer betrachtet:

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 15 von 88
Unterschied zwischen call und execute:
Immer wenn auf Methoden oder Konstruktoren
zugegriffen wird, gibt es zwei verschiedene
Zeitpunkte, die für die Ausführung wichtig sind.
Zum einen der Aufrufzeitpunkt und zum
anderem der Ausführungszeitpunkt. AspectJ
unterscheidet diese Zeitpunkte anhand von
call und execute Joinpoints. So ist es z.B. mit
call möglich auch rekursive Methodenaufrufe
abzufangen. Mit execute ist dies nicht
möglich.
Um sich den Unterschied leichter vorstellen zu
können, kann man sich merken, dass sobald
etwas bei einem Methodenaufruf passieren
soll, man call wählt. Soll etwas bei der
Ausführung eines Codeteils geschehen, wird
execute benutzt.
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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 16 von 88
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() { ... }
}

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 17 von 88
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.

Aspektorientierte Programmierung in der Praxis gezeigt am Beispiel einer J2EE Anwendung
Copyright © 2004 by Eduard Hildebrandt
Seite: 18 von 88
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 }
Ende der Leseprobe aus 88 Seiten

Details

Titel
Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung
Hochschule
Hochschule für angewandte Wissenschaften Landshut, ehem. Fachhochschule Landshut
Note
1
Autor
Jahr
2005
Seiten
88
Katalognummer
V186013
ISBN (eBook)
9783869439730
ISBN (Buch)
9783867467988
Dateigröße
1460 KB
Sprache
Deutsch
Schlagworte
aspektorientierte, programmierung, java, beispiel, anwendung
Arbeit zitieren
Eduard Hildebrandt (Autor), 2005, Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung, München, GRIN Verlag, https://www.grin.com/document/186013

Kommentare

  • Noch keine Kommentare.
Im eBook lesen
Titel: Aspektorientierte Programmierung mit Java gezeigt am Beispiel einer konkreten Anwendung


Ihre Arbeit hochladen

Ihre Hausarbeit / Abschlussarbeit:

- Publikation als eBook und Buch
- Hohes Honorar auf die Verkäufe
- Für Sie komplett kostenlos – mit ISBN
- Es dauert nur 5 Minuten
- Jede Arbeit findet Leser

Kostenlos Autor werden