Vergleich von Spring AOP und AspectJ

1. Einleitung

Es gibt heute mehrere verfügbare AOP-Bibliotheken, und diese müssen in der Lage sein, eine Reihe von Fragen zu beantworten:

  • Ist es mit meiner bestehenden oder neuen Anwendung kompatibel?
  • Wo kann ich AOP implementieren?
  • Wie schnell wird es in meine Anwendung integriert?
  • Was ist der Leistungsaufwand?

In diesem Artikel werden wir uns mit der Beantwortung dieser Fragen befassen und Spring AOP und AspectJ vorstellen - die beiden beliebtesten AOP-Frameworks für Java.

2. AOP-Konzepte

Bevor wir beginnen, lassen Sie uns einen kurzen Überblick über Begriffe und Kernkonzepte auf hoher Ebene geben:

  • Aspekt - Ein Standardcode / eine Standardfunktion, die über mehrere Stellen in der Anwendung verteilt ist und sich normalerweise von der tatsächlichen Geschäftslogik unterscheidet (z. B. Transaktionsverwaltung). Jeder Aspekt konzentriert sich auf eine bestimmte Querschnittsfunktionalität
  • Joinpoint - Dies ist ein bestimmter Punkt während der Ausführung von Programmen wie Methodenausführung, Konstruktoraufruf oder Feldzuweisung
  • Hinweis - Die Aktion, die der Aspekt in einem bestimmten Joinpoint ausführt
  • Pointcut - ein regulärer Ausdruck, der einem Joinpoint entspricht. Jedes Mal, wenn ein Verbindungspunkt mit einem Punktschnitt übereinstimmt, wird ein bestimmter Hinweis ausgeführt, der diesem Punktschnitt zugeordnet ist
  • Weben - der Prozess des Verknüpfen von Aspekten mit Zielobjekten, um ein empfohlenes Objekt zu erstellen

3. Spring AOP und AspectJ

Lassen Sie uns nun Spring AOP und AspectJ auf einer Reihe von Achsen diskutieren - wie z. B. Fähigkeiten, Ziele, Webart, interne Struktur, Verbindungspunkte und Einfachheit.

3.1. Fähigkeiten und Ziele

Einfach ausgedrückt haben Spring AOP und AspectJ unterschiedliche Ziele.

Spring AOP zielt darauf ab, eine einfache AOP-Implementierung in Spring IoC bereitzustellen, um die häufigsten Probleme zu lösen, mit denen Programmierer konfrontiert sind. Es ist nicht als vollständige AOP-Lösung gedacht - es kann nur auf Bohnen angewendet werden, die von einem Spring-Container verwaltet werden.

Andererseits ist AspectJ die ursprüngliche AOP-Technologie, die darauf abzielt, eine vollständige AOP-Lösung bereitzustellen. Es ist robuster, aber auch wesentlich komplizierter als Spring AOP. Es ist auch erwähnenswert, dass AspectJ auf alle Domänenobjekte angewendet werden kann.

3.2. Weberei

Sowohl AspectJ als auch Spring AOP verwenden unterschiedliche Webarten, die sich auf das Verhalten in Bezug auf Leistung und Benutzerfreundlichkeit auswirken.

AspectJ verwendet drei verschiedene Arten des Webens:

  1. Weben zur Kompilierungszeit : Der AspectJ-Compiler verwendet sowohl den Quellcode unseres Aspekts als auch unserer Anwendung als Eingabe und erstellt als Ausgabe gewebte Klassendateien
  2. Nachkompiliertes Weben : Dies wird auch als binäres Weben bezeichnet. Es wird verwendet, um vorhandene Klassendateien und JAR-Dateien mit unseren Aspekten zu verweben
  3. Ladezeitweben : Dies ist genau wie beim früheren binären Weben, mit dem Unterschied, dass das Weben verschoben wird, bis ein Klassenladeprogramm die Klassendateien in die JVM lädt

Weitere Informationen zu AspectJ selbst finden Sie in diesem Artikel.

Da AspectJ das Weben von Kompilierungszeit und Klassenladezeit verwendet, verwendet Spring AOP das Weben zur Laufzeit .

Beim Laufzeitweben werden die Aspekte während der Ausführung der Anwendung mithilfe von Proxys des Zielobjekts gewebt - entweder mithilfe des dynamischen JDK-Proxys oder des CGLIB-Proxys (die im nächsten Punkt erläutert werden):

3.3. Interne Struktur und Anwendung

Spring AOP ist ein Proxy-basiertes AOP-Framework. Dies bedeutet, dass zum Implementieren von Aspekten für die Zielobjekte Proxys dieses Objekts erstellt werden. Dies wird auf zwei Arten erreicht:

  1. JDK Dynamic Proxy - der bevorzugte Weg für Spring AOP. Immer wenn das Zielobjekt nur eine Schnittstelle implementiert, wird der dynamische JDK-Proxy verwendet
  2. CGLIB-Proxy - Wenn das Zielobjekt keine Schnittstelle implementiert, kann der CGLIB-Proxy verwendet werden

Weitere Informationen zu Spring AOP-Proxy-Mechanismen finden Sie in den offiziellen Dokumenten.

AspectJ hingegen macht zur Laufzeit nichts, da die Klassen direkt mit Aspekten kompiliert werden.

Im Gegensatz zu Spring AOP sind daher keine Designmuster erforderlich. Um die Aspekte in den Code einzubinden, wird der als AspectJ-Compiler (ajc) bekannte Compiler eingeführt, über den wir unser Programm kompilieren und dann ausführen, indem wir eine kleine Laufzeitbibliothek (<100 KB) bereitstellen.

3.4. Joinpoints

In Abschnitt 3.3 haben wir gezeigt, dass Spring AOP auf Proxy-Mustern basiert. Aus diesem Grund muss die Ziel-Java-Klasse in Unterklassen unterteilt und Querschnittsthemen entsprechend angewendet werden.

Aber es kommt mit einer Einschränkung. Wir können keine übergreifenden Bedenken (oder Aspekte) auf Klassen anwenden, die „endgültig“ sind, da sie nicht überschrieben werden können und daher zu einer Laufzeitausnahme führen würden.

Gleiches gilt für statische und endgültige Methoden. Frühlingsaspekte können nicht auf sie angewendet werden, da sie nicht überschrieben werden können. Daher unterstützt Spring AOP aufgrund dieser Einschränkungen nur Verbindungspunkte für die Methodenausführung.

Allerdings webt AspectJ den Querschnitt Anliegen direkt in den eigentlichen Code vor der Laufzeit. Im Gegensatz zu Spring AOP muss das Zielobjekt nicht in Unterklassen unterteilt werden, und daher werden auch viele andere Joinpoints unterstützt. Im Folgenden finden Sie eine Zusammenfassung der unterstützten Joinpoints:

Joinpoint Spring AOP unterstützt AspectJ unterstützt
Methodenaufruf Nein Ja
Methodenausführung Ja Ja
Konstruktoraufruf Nein Ja
Konstruktorausführung Nein Ja
Statische Initialisierungsausführung Nein Ja
Objektinitialisierung Nein Ja
Feldreferenz Nein Ja
Feldzuordnung Nein Ja
Handler-Ausführung Nein Ja
Beratung Ausführung Nein Ja

Es ist auch erwähnenswert, dass in Spring AOP Aspekte nicht auf die Methode angewendet werden, die innerhalb derselben Klasse aufgerufen wird.

Das liegt natürlich daran, dass wir beim Aufrufen einer Methode innerhalb derselben Klasse nicht die Methode des von Spring AOP bereitgestellten Proxys aufrufen. Wenn wir diese Funktionalität benötigen, müssen wir eine separate Methode in verschiedenen Beans definieren oder AspectJ verwenden.

3.5. Einfachheit

Spring AOP ist offensichtlich einfacher, da es keinen zusätzlichen Compiler oder Weber zwischen unseren Erstellungsprozessen einführt. Es verwendet Laufzeitweberei und lässt sich daher nahtlos in unseren üblichen Erstellungsprozess integrieren. Obwohl es einfach aussieht, funktioniert es nur mit Bohnen, die von Spring verwaltet werden.

Um AspectJ verwenden zu können, müssen wir jedoch den AspectJ-Compiler (ajc) einführen und alle unsere Bibliotheken neu verpacken (es sei denn, wir wechseln zum Weben nach dem Kompilieren oder zum Laden während der Ladezeit).

Dies ist natürlich komplizierter als das erstere - da es AspectJ Java Tools (die einen Compiler (ajc), einen Debugger (ajdb), einen Dokumentationsgenerator (ajdoc) und einen Programmstrukturbrowser (ajbrowser) enthalten) einführt müssen entweder in unsere IDE oder das Build-Tool integriert werden.

3.6. Performance

In Bezug auf die Leistung ist das Weben zur Kompilierungszeit viel schneller als das Weben zur Laufzeit . Spring AOP ist ein Proxy-basiertes Framework, daher werden zum Zeitpunkt des Anwendungsstarts Proxys erstellt. Außerdem gibt es einige weitere Methodenaufrufe pro Aspekt, was sich negativ auf die Leistung auswirkt.

Auf der anderen Seite verwebt AspectJ die Aspekte vor der Ausführung der Anwendung in den Hauptcode, sodass im Gegensatz zu Spring AOP kein zusätzlicher Laufzeitaufwand entsteht.

Aus diesen Gründen legen die Benchmarks nahe, dass AspectJ fast 8- bis 35-mal schneller ist als Spring AOP.

4. Zusammenfassung

Diese kurze Tabelle fasst die wichtigsten Unterschiede zwischen Spring AOP und AspectJ zusammen:

Frühling AOP AspektJ
In reinem Java implementiert Implementiert mit Erweiterungen der Programmiersprache Java
Kein separater Kompilierungsprozess erforderlich Benötigt AspectJ-Compiler (ajc), sofern LTW nicht eingerichtet ist
Es ist nur Laufzeitweben verfügbar Laufzeitweberei ist nicht verfügbar. Unterstützt das Weben während der Kompilierung, nach der Kompilierung und beim Laden
Weniger leistungsfähig - unterstützt nur das Weben auf Methodenebene Leistungsstärker - kann Felder, Methoden, Konstruktoren, statische Initialisierer, endgültige Klassen / Methoden usw. weben.
Kann nur auf Beans implementiert werden, die von Spring Container verwaltet werden Kann auf allen Domänenobjekten implementiert werden
Unterstützt nur Pointcuts für die Methodenausführung Unterstützt alle Pointcuts
Proxys werden aus Zielobjekten erstellt, und Aspekte werden auf diese Proxys angewendet Aspekte werden direkt in Code verwoben, bevor die Anwendung ausgeführt wird (vor der Laufzeit).
Viel langsamer als AspectJ Bessere Leistung
Einfach zu erlernen und anzuwenden Vergleichsweise komplizierter als Spring AOP

5. Auswahl des richtigen Frameworks

Wenn wir alle in diesem Abschnitt vorgebrachten Argumente analysieren, werden wir verstehen, dass ein Framework überhaupt nicht besser ist als ein anderes.

Einfach ausgedrückt hängt die Wahl stark von unseren Anforderungen ab:

  • Framework: Wenn die Anwendung kein Spring Framework verwendet, haben wir keine andere Wahl, als die Idee der Verwendung von Spring AOP fallen zu lassen, da nichts verwaltet werden kann, was außerhalb der Reichweite von Spring Container liegt. Wenn unsere Anwendung jedoch vollständig mit dem Spring Framework erstellt wird, können wir Spring AOP verwenden, da es einfach zu erlernen und anzuwenden ist
  • Flexibilität: Angesichts der eingeschränkten Joinpoint-Unterstützung ist Spring AOP keine vollständige AOP-Lösung, löst jedoch die häufigsten Probleme, mit denen Programmierer konfrontiert sind. Wenn wir jedoch tiefer gehen und AOP maximal nutzen möchten und die Unterstützung von einer Vielzahl verfügbarer Joinpoints wünschen, ist AspectJ die richtige Wahl
  • Leistung: Wenn wir begrenzte Aspekte verwenden, gibt es geringfügige Leistungsunterschiede. Es gibt jedoch manchmal Fälle, in denen eine Anwendung mehr als Zehntausende von Aspekten aufweist. In solchen Fällen möchten wir kein Laufzeitweben verwenden, daher ist es besser, sich für AspectJ zu entscheiden. AspectJ ist bekanntermaßen 8- bis 35-mal schneller als Spring AOP
  • Das Beste von beiden: Beide Frameworks sind vollständig miteinander kompatibel. Wir können Spring AOP immer nutzen, wann immer dies möglich ist, und AspectJ weiterhin verwenden, um Unterstützung für Joinpoints zu erhalten, die von ersteren nicht unterstützt werden

6. Fazit

In diesem Artikel haben wir sowohl Spring AOP als auch AspectJ in mehreren Schlüsselbereichen analysiert.

Wir haben die beiden AOP-Ansätze sowohl hinsichtlich der Flexibilität als auch hinsichtlich der einfachen Anpassung an unsere Anwendung verglichen.