Was ist AOP
AOP (Aspekt-orientierte Programmierung, Aspekt-orientierte Programmierung) kann als Ergänzung und Verbesserung der OOP (objektorientierte Programmierung) sein. OOP führt Konzepte wie Kapselung, Vererbung und Polymorphismus ein, um eine Objekthierarchie zu etablieren, um eine Sammlung öffentlicher Verhaltensweisen zu simulieren. Wenn wir verstreute Objekten öffentliches Verhalten einführen müssen, scheint OOP machtlos zu sein. Das heißt, OOP ermöglicht es Ihnen, Beziehungen von oben nach unten zu definieren, ist jedoch nicht geeignet, um Beziehungen von links nach rechts zu definieren. Zum Beispiel die Protokollierungsfunktion. Der Protokollcode wird häufig horizontal über alle Objektebenen verstreut, ohne dass es sich um die Kernfunktionalität des Objekts handelt, auf das es verstreut ist. Gleiches gilt für andere Arten von Code wie Sicherheit, Ausnahmebehandlung und Transparenz. Diese Art von irrelevantem Code, der überall verstreut ist, wird als Cross-Cuting-Code bezeichnet. Im OOP -Design verursacht es eine Menge Code -Duplikation, was der Wiederverwendung jedes Moduls nicht förderlich ist.
Einführung
Das Java -Designmuster, das ich vor einiger Zeit geschrieben habe - das Proxy -Muster. Kürzlich, als ich mir die Frühlings -AOP ansah, hatte ich das Gefühl, dass es enge Verbindungen im Proxy -Muster geben sollte, also entschied ich mich, das Implementierungsprinzip der Frühlings -AOP zu verstehen.
Apropos AOP, wir müssen über OOP sprechen. Die Konzepte der Kapselung, der Vererbung und des Polymorphismus werden in OOP eingeführt, um eine Objekthierarchie zu etablieren, um eine Sammlung öffentlicher Verhaltensweisen zu simulieren. Wenn wir jedoch gemeinsame Teile für einige Objekte einführen müssen, führt OOP eine Menge doppelter Code ein. Zum Beispiel: Protokollierungsfunktion.
Die AOP -Technologie verwendet eine Technik, die als "Kreuzschneidung" bezeichnet wird, um das Innere des eingekapselten Objekts zu zerlegen und die gemeinsamen Verhaltensweisen zu verkapulieren, die mehrere Klassen in ein wiederverwendbares Modul beeinflussen, das die Duplikation des Systems durch das System von Code verringern, die Kopplung zwischen Modulen reduzieren und zukünftige Betriebsfähigkeit und Wartung erleichtern. AOP unterteilt das Softwaresystem in zwei Teile: Kernprobleme und kreuzreiche Aufmerksamkeit. Der Hauptprozess der Geschäftsverarbeitung ist der zentrale Schwerpunkt und der Teil, der wenig damit zu tun hat, ist der Querschnittsfokus. Ein Merkmal für Übergreifende Bedenken ist, dass sie häufig in mehreren Kernproblemen auftreten und überall im Grunde ähnlich sind. Zum Beispiel Berechtigungsauthentifizierung, Protokollierung und Transaktionsverarbeitung.
Implementierungsprinzip
Als ich den Proxy -Modus lernte, erfuhr ich, dass der Proxy -Modus in dynamische Proxy und statische Proxy unterteilt ist. Jetzt werden wir zuerst unser eigenes AOP -Framework basierend auf dem Proxy -Modell implementieren und dann die Implementierungsprinzipien von Spring AOP untersuchen.
Erstens wird es mit einem statischen Stellvertreter implementiert. Der Schlüssel zum statischen Proxy besteht darin, eine gemeinsame Schnittstelle zwischen dem Proxy -Objekt und dem Zielobjekt zu implementieren, und das Proxy -Objekt enthält einen Verweis auf das Zielobjekt.
Öffentlicher Schnittstellencode:
öffentliche Schnittstelle iHello {/*** Business -Methode*@param str*/void Sayhello (String Str);} Zielklassencode: öffentliche Klasse Hallo implementiert iHello {@Overridepublic void Sayhello (String Str) {System.out.println ("Hallo"+Str); Für den Proxy -Klassencode fügen wir eine Protokollierungsfunktion hinzu und führen bestimmte Methoden vor und nach dem Start der Methode aus. Ist es nicht besonders ähnlich wie AOP?
Proxyhello im öffentlichen Klassen implementiert Ihello {privat ihello Hallo; public proxyhello (ihello Hallo) {Super (); this.hello = hello;}@oversidepublic void SayShello (String Str) {logger.start (); // Fügen Sie die spezifische Methode Hello.sayhello (str); Logger.end ();}} hinzu Protokollklassencode:
public class logger {public static void start () {System.out.println (neuer Date ()+ "Hello start ...");} public static void end () {System.out.println (New Date)+ "Say Hello End");}}}}} Testcode:
public class test {public static void main (String [] args) {iHello hello = new Proxyhello (new Hello ()); // Wenn wir eine Protokollierungsfunktion benötigen, verwenden Sie Proxy -Klasse // iHello Hallo = new Hello (); // Wenn wir keine Protokollierungsfunktion verwenden, verwenden Sie die Zielklasse Hello.sayhello ("morgen"); }}Auf diese Weise implementieren wir die einfachste AOP, aber es wird ein Problem geben: Wenn wir viele Klassen wie Hallo haben, sollten wir dann viele Klassen wie Helloproxy schreiben? Tatsächlich ist es auch eine sehr mühsame Sache. Nach JDK1.3 bietet JDK uns eine API java.lang.reflect.invocationHandler -Klasse. Mit dieser Klasse können wir dynamisch etwas für einige Methoden tun, wenn der JVM die Methoden einer bestimmten Klasse aufruft. Lassen Sie uns die Implementierung von Dynamic Proxy implementieren.
Die dynamische Proxy -Implementierung implementiert hauptsächlich InvocationHandler und injiziert das Zielobjekt in das Proxy -Objekt unter Verwendung des Reflexionsmechanismus, um die Zielobjektmethode auszuführen.
Die Schnittstellenimplementierung entspricht dem statischen Proxy, dem Proxy -Klassencode:
Public Class Dynaproxyhello implementiert InvocationHandler {private Objektziel; // Zielobjekt/*** Instantieren Sie das Zielobjekt durch Reflexion* @param Object* @return*/public Object Bind (Objektobjekt) {this.target = Object; return proxy.newproxyinstance (this.target.getClas). this);}@oversidePublic Object Invoke (Objektproxy, Methode Methode, Object [] args) löst Throwable {Object ergebnis = null; logger.start (); // Zusätzliche Methoden hinzufügen // Methoden zum Ausführen von Zielobjekten über Reflection Mechanism Ergebnis = Methode.invoke (this.target, args); logger.end (); Testklassencode:
public class dynatest {public static void main (String [] args) {ihello hello = (ihello) New Dynaproxyhello (). Bind (new Hello ()); // Wenn wir eine Protokollierungsfunktion verwenden müssen, verwenden Sie Proxy -Klasse // iHello = new Hello (). Nach dem Lesen des obigen Code kann es im Vergleich zu Frühlings -AOP ein Problem geben. Die Protokollklasse kann erst vor und nach der Methode gedruckt werden, AOP sollte jedoch ausgeführt werden können, wenn die Bedingungen erfüllt sind. Kann das gesamte Dynapoxyhello -Objekt und das Log -Operation -Objekt (Logger) entkoppelt werden?
In der folgenden Code -Implementierung wird das Dynapoxyhello -Objekt und das Log -Operation -Objekt (Logger) entkoppeln:
Wir müssen den Protokolloperationscode (oder einen anderen Betriebscode) vor oder nach der Methode des Proxy -Objekts hinzufügen. Dann können wir eine Schnittstelle mit nur zwei Methoden abstrahieren: Eine ist die Methode, die vor dem Proxy -Objekt ausgeführt wird, um die Methode auszuführen. Wir haben es Start genannt, und die zweite Methode ist die Methode, die nach dem Ausführen des Proxy -Objekts die Methode ausgeführt hat, und wir haben sie zum Ende genannt.
Logger -Schnittstelle:
öffentliche Schnittstelle Iloogger {void start (Methode Methode); void End (Methode Methode);} Implementierung der Logger -Schnittstelle:
public class dlogger implementiert ilogger {@Overridepublic void start (Methode Methode) {System.out.println (new Date () + method.getName () + "Hallo Start ...");}@oversidepublic void End (Methode Methode) {system.println (New Date () + Method () method () + + Dynamische Proxyklasse:
public class dynaproxyhello implements invocationHandler {// anrufen von private object proxy; // Zielobjekt privates Objektziel; öffentliches Objekt Bind (Objektziel, Objekt proxy) {this.target = target; this.proxy = proxy; proxy.newproxyInstance (this.target.getClasses (). this.target.getClass (). getInterfaces (), this);}@oversidepublic Object invoke (Objektproxy, Methode Methode, Objekt [] args) wirft Throwable {Object result = null; // Reflection des Operators Instance Class Clazz = this this.proxy.getClasse (). Class [] {method.class}); // Reflection führt die Startmethode start.invoke (this.proxy, neues Objekt [] {this.proxy.getClass ()}); // Fügt die ursprüngliche Methode zur Verarbeitung der Objektmethode.invoke (this.target, args); // Reflection -Reflection -Endmethode die Operator -End -Methode durch. Class [] {method.class}); // Reflection führt die Endmethode end.invoke (this.proxy, neues Objekt [] {Methode}); Rückgabeergebnis;}} aus. Testcode:
public class dynatest {public static void main (String [] args) {ihello hello = (ihello) new Dynaproxyhello (). Bind (new Hello (), new Dlogger (); // Wenn wir eine Protokollierungsfunktion verwenden, verwenden Sie die Proxy -Klasse // iHello Hallo = neue (). Hello.sayhello ("morgen");}} Im obigen Beispiel können wir feststellen, dass die Funktion von AOP durch dynamische Proxying- und Übertragungstechnologie im Grunde genommen implementiert wurde. Wenn wir das Protokoll nur vor der Ausführung der Methode drucken müssen, können wir die Methode end () nicht implementieren, damit wir den Druckzeitpunkt steuern können. Wenn wir möchten, dass die angegebene Methode das Protokoll ausdrucken, müssen wir der Methode der Methode nur ein Urteil über den Methodennamen hinzufügen. Der Methodenname kann in der XML -Datei geschrieben werden, damit wir ihn mit der Konfigurationsdatei entkoppeln können, damit wir ein einfaches Feder -AOP -Framework implementieren.
Der obige Inhalt ist das vom Herausgeber vorgelegte Spring AOP -Implementierungsprinzip. Ich hoffe, es wird für Sie hilfreich sein!