Frühlings -AOP -Benachrichtigungen sind in fünf Kategorien unterteilt:
Vor Rat: Führen Sie vor dem Verbindungspunkt aus. Die Vorschau beeinträchtigt nicht die Ausführung des Verbindungspunkts, es sei denn, hier wird eine Ausnahme ausgelöst.
Normale Return -Benachrichtigung [Nach Rückgabe der Beratung]: Ausführen nach der normalen Ausführung des Verbindungspunkts wird ausgeführt. Wenn eine Ausnahme vom Verbindungspunkt ausgelöst wird, wird sie nicht ausgeführt.
Ausnahmeberückgabe -Benachrichtigung [Nach dem Wurfanzug]: Ausführen nach einer Ausnahme durch den Verbindungspunkt.
Rückgabebenachrichtigung [Nach (schließlich) Ratschläge]: Nach Abschluss der Ausführung wird der Inhalt der Rückgabemitteilung ausgeführt, unabhängig davon, ob sie normal abgeschlossen ist oder eine Ausnahme ausgelöst wird.
Um Rat rund um den Rat: Ratschläge umgeben den Verbindungspunkt, z. B. vor und nach einem Methodenaufruf. Dies ist der leistungsstärkste Benachrichtigungsart, der einige Vorgänge vor und nach Methodenaufrufen anpassen kann.
Die umgebende Benachrichtigung muss auch entscheiden, ob die Verarbeitung des Join -Punktes (die Prozessmethode des Proceedingjoinpoint) oder die Interrupt -Ausführung fortgesetzt werden soll.
Als nächstes werden wir fünf Benachrichtigungstypen testen, indem wir ein Beispielprogramm schreiben:
Schnittstelle definieren
Paket com.chenqa.springaop.example.service; public interface banksService { / *** Simulierter Bankübertragung* @param vom Konto* @param zu Konto* @param Kontoübertragung* @return* / public boolean Transfer (String Form, String to, Double Account);}Implementierungsklassen schreiben
paket com.chenqa.springaop.example.service.impl; import com.chenqa.springaop.example.service.banksservice; yuan "); } System.out.println (Form+"Übertragung auf"+bis+Bankkonto "+Konto+" yuan "); false zurückgeben; }}
Ändern Sie die Federkonfigurationsdatei und fügen Sie Folgendes hinzu:
<!-BankService Bean-> <bean id = "banksService"/> <!-Abschnitt-> <bean id = "myaspespe"/> <!-AOP-Konfiguration-> <AOP: config> <aoP: Aspekt ref = "myaspect"> <aoP: pointcut expression = "execution (*com.chenqa.spring.)). id="pointcut"/> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/> <AOP: um Methode = "um" pointcut-ref = "pointcut"/> </aoP: Aspekt> </aop: config>
Schreiben eines Testprogramms
ApplicationContext context = new classPathXmlApplicationContext ("Spring-Aop.xml"); Banksservice banksservice = context.getbean ("banksservice", banksservice.class); Bankservice.Transfer ("Zhang San", "Li Si", 200); Ausgabe nach Ausführung:
Ändern Sie 200 im Testprogramm auf 50 und geben Sie dann nach der Ausführung aus: Ausgabe:
Aus den Testergebnissen ist ersichtlich, dass die Ausführungsreihenfolge der fünf Benachrichtigungen lautet:
Vorabmessung → Umgebung Benachrichtigung → Normale Return-Benachrichtigung/Ausnahme-Return-Benachrichtigung → Rückgabebenachrichtigung, Sie können mehrmals zur Anzeige durchführen.
Fall 1: Eine Methode wird nur von einer Aspektklasse abgefangen
Wenn eine Methode von nur einem Aspekt abgefangen wird, in welcher Reihenfolge werden die verschiedenen Ratschläge in diesem Aspekt ausgeführt? Bitte siehe:
Hinzufügen von Pointcut -Klasse
Mit diesem Pointcut werden alle Methoden in allen Klassen im Testpaket abgefangen.
Pakettest; importieren org.aspespectj.lang.annotation
Aspektklasse hinzufügen
Der Rat in dieser Klasse wird den oben genannten Pointcut verwenden. Bitte beachten Sie das Wertattribut jedes Rates, wenn Sie ihn verwenden.
Paketstest; import org.aspespectj.lang.joinpoint; import org.aspespectj.lang.proceedingjoinpoint; import org.aspespectj.lang.Annotation. joinpoint) {System.out.println ("[Aspekt1] vor Rat"); } @Around (value = "test.pointcuts.aopdemo ()") public void in Around (ProseingJoInpoint PJP) löst Throwable {System.out.println ("[Aspekt1] um Rat 1"); pjp.procece (); System.out.println ("[Aspekt1] um Rat2"); } @AfterReturning (value = "test.pointcuts.aopdemo ()") public void atturning (joinpoint joinpoint) {system.out.println ("[Aspekt1] AfterReturning -Rat"); } @Afterthring (value = "test.pointcuts.aopDemo ()") public void attheThrowing (joinpoint joinpoint) {System.out.println ("[Aspekt1] After -Throwing -Rat"); } @After (value = "test.pointcuts.aopDemo ()") public void nach (joinpoint joinpoint) {System.out.println ("[Aspekt1] ättigende Ratschläge"); } @After (value = "test.pointcuts.aopdemo ()") public void nach (joinpoint joinpoint) {System.out.println ("[Aspekt1] nach dem Rat"); }}Fügen Sie einen Testcontroller hinzu
Fügen Sie einen Controller zum Testen hinzu. In diesem Controller gibt es nur eine Methode, die jedoch je nach den Parameterwerten unterschiedlich behandelt wird: Eine besteht darin, ein Objekt normal zurückzugeben, und die andere ist eine Ausnahme (weil wir den @Afterthrodern -Rat testen möchten)
Pakettest; importieren test.exception.TestException; import org.springframework.http.httpstatus; import org.springframework.web.bind.annotation. @RequestMapping (value = "/test", method = requestMethod.get) öffentlicher Ergebnistest (@RequestParam boolean throwException) {// Fall 1 if (throwException) {System.out.println ("eine Ausnahme werfen"); Neue testException ("eine Serverausnahme verspotten"); } // case 2 system.out.println ("Test OK"); Neue Ergebnisse zurückgeben () {{this.setId (111); this.setName ("verspotten ein Ergebnis"); }}; } public static class Ergebnis {private int id; privater Zeichenfolge Name; public int getid () {return id; } public void setId (int id) {this.id = id; } public String getName () {return name; } public void setName (String -Name) {this.name = name; }}}Normale Situation testen
Geben Sie die folgende URL direkt im Browser ein und geben Sie ein: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
Wir werden das Ausgabeergebnis sehen:
[Aspekt1] In Bezug
Testausnahmen
Geben Sie direkt die folgende URL in den Browser ein und drücken Sie die Eingabetaste: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
Wir werden das Ausgabeergebnis sehen:
[Aspekt1] Um Rat 1 [Aspekt1] Vor dem Beratung einer Ausnahme [Aspekt1] nach Ratschlägen [Aspekt1] Nachfolger von Nachfolger
abschließend
Wenn eine Methode von nur einer Aspektklasse abgefangen wird, wird der Rat innerhalb der Aspektklasse in der folgenden Reihenfolge ausgeführt:
Normale Situation:
Ausnahme:
Fall 2: Die gleiche Methode wird durch mehrere Aspektklassen abgefangen
Hier ist ein Beispiel, das von zwei Aspektklassen abgefangen wird.
In einigen Fällen kann für zwei verschiedene Aspektklassen unabhängig davon, ob ihr Rat dieselbe Pointcut oder unterschiedliche Pointcuts verwendet, dieselbe Methode von mehreren Aspektklassen abgefangen werden. In diesem Fall werden in welcher Reihenfolge die Beratung in diesen mehreren Aspektklassen ausgeführt? Bitte siehe:
Die Pointcut -Klasse bleibt unverändert
Fügen Sie eine neue Aspektklasse hinzu
Paketstest; import org.aspespectj.lang.joinpoint; import org.aspespectj.lang.proceedingjoinpoint; import org.aspespectj.lang.Annotation. JoinPoint) {System.out.println ("[Aspekt2] vor Rat"); } @Around (value = "test.pointcuts.aopdemo ()") public void in Around (Proceedingjoinpoint PJP) löscht Throwable {System.out.println ("[Aspekt2] um Rat 1"); pjp.procece (); System.out.println ("[Aspekt2] um Rat2"); } @AfterReturning (value = "test.pointcuts.aopdemo ()") public void atturning (joinpoint joinpoint) {System.out.println ("[Aspekt2] AfterReturning -Rat"); } @Afterthrowing (value = "test.pointcuts.aopDemo ()") public void attheThrowing (joinpoint joinpoint) {System.out.println ("[Aspekt2] After -Throwing -Rat"); } @After (value = "test.pointcuts.aopdemo ()") public void nach (joinpoint joinpoint) {System.out.println ("[Aspekt2] Nachbekämpfung"); } @After (value = "test.pointcuts.aopdemo ()") public void nach (joinpoint joinpoint) {System.out.println ("[Aspekt2] nach dem Rat"); }}Der Testcontroller ist ebenfalls unverändert
Verwenden Sie immer noch den Controller oben. Aber jetzt fangen sowohl Aspekt1 als auch Aspekt2 die Methoden im Controller ab.
Testen Sie weiter unten!
Normale Situation testen
Geben Sie die folgende URL direkt im Browser ein und geben Sie ein: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
Wir werden das Ausgabeergebnis sehen:
[Aspekt2] In Bezug
Aber zu diesem Zeitpunkt kann ich nicht schließen, dass Aspekt2 definitiv vor Aspekt1 ausgeführt wird.
Glauben Sie es nicht? Sie starten den Server neu und versuchen es erneut. Vielleicht sehen Sie die folgenden Ausführungsergebnisse:
[Aspekt1] In Bezug
Das heißt, in diesem Fall ist die Ausführungsreihenfolge von Aspekt1 und Aspekt2 unbekannt. Wie kann man es also lösen? Keine Eile, die Lösung wird unten angegeben.
Testausnahmen
Geben Sie direkt die folgende URL in den Browser ein und drücken Sie die Eingabetaste: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
Wir werden das Ausgabeergebnis sehen:
[Aspekt2] In Bezug
Wenn Sie den Server neu starten und ihn dann erneut testen, sehen Sie möglicherweise die folgenden Ergebnisse:
[Aspekt1] Um Rat 1 [Aspekt1] vor Rat [Aspekt2] um Rat 1 [Aspekt2] Bevor Sie eine Ausnahme [Aspekt2] Nachfolger [Aspekt1] Nachbewegungsberatung durchführen [Aspekt2]
Das heißt, auf die gleiche Weise ist die Ausführungsreihenfolge von Aspekt1 und Aspekt2 unter außergewöhnlichen Umständen ebenfalls unbestimmt.
Wie geben Sie in Fall 2 die Ausführungsreihenfolge jedes Aspekts an?
Es gibt zwei Methoden:
Unabhängig davon, welche Methode verwendet wird, desto kleiner wird der Aspekt, desto mehr wird es zuerst ausgeführt.
Zum Beispiel fügen wir @Order -Anmerkungen für Apsect1 bzw. Aspekt2 wie folgt hinzu:
@Order (5)@component@Aspektpublic Class Aspekt1 {// ...}@order (6)@component@Aspektpublic Class Aspekt2 {// ...} Nach dieser Änderung kann sichergestellt werden, dass der Rat in Aspekt1 in jedem Fall immer vor dem Rat in Aspekt2 ausgeführt wird. Wie in der Abbildung unten gezeigt:
Notiz
Wenn zwei identische Ratschläge für denselben Pointcut definiert sind (z. B. zwei @before) sind definiert, kann die Ausführungsreihenfolge dieser beiden Ratschläge nicht ermittelt werden, selbst wenn Sie die @Order -Annotation zu diesen beiden Ratschlägen hinzufügen, funktioniert sie nicht. Denken Sie daran.
Für die @Around -Ratschläge muss es unabhängig davon, ob er einen Rückgabewert hat oder nicht, PJP.Procece () innerhalb der Methode aufrufen. Andernfalls wird die Schnittstelle im Controller nicht ausgeführt, wodurch auch die @before -Ratschläge nicht ausgelöst werden. Zum Beispiel gehen wir davon aus, dass unter normalen Umständen die Ausführungsreihenfolge "Aspekt2 -> Apsect1 -> Controller" lautet. Wenn wir pjp.procece () löschen; In @around in Aspekt1 wird der Ausgang, den wir sehen, sein:
[Aspekt2] Um Rat 1 [Aspekt2] vor Rat [Aspekt1] Um Rat 1 [Aspekt1] Um Rat2 [Aspekt1] Nach Rat [Aspekt1] Nachreturning -Rat [Aspekt2] um Rat2 [Aspekt2] Nachwuchsabrechnung
Aus den Ergebnissen können wir feststellen, dass die Schnittstelle in Controller nicht ausgeführt wurde, und @Beforeadvice in Aspekt1 wurde ebenfalls nicht ausgeführt.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.