@Transactional @Async und andere Anmerkungen funktionieren nicht
Zuvor haben viele Menschen einige Situationen gestoßen, in denen die Annotation bei der Verwendung von @Transactional, @aSync und anderen Anmerkungen im Frühjahr nicht funktioniert.
Warum treten diese Situationen auf? Da die Funktionen dieser Anmerkungen tatsächlich durch Spring AOP implementiert werden und ihre Implementierungsprinzipien durch Proxy umgesetzt werden.
JDK Dynamic Proxy
Lassen Sie uns die Grundprinzipien des JDK -dynamischen Proxy mit einem einfachen Beispiel verstehen:
// Zielklasse Schnittstelle öffentliche Schnittstelle jdkproxyTestService {void run ();} // Zielklasse öffentliche Klasse jdkproxyTestServiceImplemente implementiert jdkproxyTestService {public void run () {system.out.println ("Do etwas ..."); }} // Proxy Class Public Class TestjdkProxy implementiert InvocationHandler {private Object targetObject; // Proxy -Zielobjekt // Konstruieren Sie das Proxy -Objekt öffentliches Objekt NewProxy (Object targetObject) {this.targetObject = targetObject; return proxy.newproxyInstance (targetObject.getClass (). getClassLoader (), targetObject.getClass (). getInterfaces (), this); } // Reflection verwenden, um eine logische Verbesserung des ursprünglichen logischen öffentlichen Objekts aufzurichten (Objektproxy, Methode, Objekt [] args) löscht Throwable {// Transaktionsstart AssoteGeginTransaction () aus. // Original Ausführungslogik -Objekt ret = methode.invoke (targetObject, args); // Mock Transaction Submission AsomeCommittransaction (); Rückkehr; } private void asumebeginTransaction () {System.out.println ("Mock Transaction Start ..."); } private void asomeCommittransaction () {System.out.println ("Mock Transaction Submission ..."); }} // public class test {public static void main (String [] args) {testjdkproxy jdkproxy = new Testjdkproxy (); JdkproxyTestService proxy = (jdkproxyTestService) jdkproxy.newproxy (New JdkproxyTestServiceImpl ()); Proxy.run (); }}Das obige Beispiel sollte in der Lage sein, das Prinzip des JDK -dynamischen Proxy klar zu erklären. Es verwendet den Reflexionsmechanismus, um eine anonyme Klasse zu generieren, die die Proxy -Schnittstelle implementiert, und aufgerufen in IvokeHandler, bevor Sie die spezifische Methode aufrufen. Wenn wir eine Methode über ein Proxy -Klassen -Objekt aufrufen, werden wir zuerst ihre Invoke -Methode aufrufen und dann die ursprüngliche Methode aufrufen. Auf diese Weise können wir vor und nach der ursprünglichen Methodenlogik einheitlich einheitlich verarbeitende Logik hinzufügen.
Spring hat auch eine dynamische Proxy -Methode, die CGGLIB Dynamic Proxy ist. Es lädt die Klassendatei der Proxy -Objektklasse und verarbeitet sie, indem der Bytecode geändert wird, um Unterklassen zu generieren. Obwohl die Handhabungsmethoden unterschiedlich sind, sind die Ideen der Agentur konsistent.
Wenn das mit Proxyed für das Ziel stellte Ziel eine Schnittstelle implementiert, verwendet Spring standardmäßig JDK Dynamic Proxy. Alle von diesem Zieltyp implementierten Schnittstellen werden proxyiert. Wenn das Zielobjekt keine Schnittstelle implementiert, wird ein CGGLIB -Proxy erstellt.
Frühlings -AOP -Annotationsversagen und Lösung
Basierend auf der obigen Analyse des dynamischen Proxy -Prinzips schauen wir uns die folgenden zwei häufigen Probleme an:
In derselben Klasse ist Methode A auf dem Aufruf von Methode B (mit der Methode B) und die Annotation ungültig.
Wenn für alle Frühlings -AOP -Anmerkungen solche Anmerkungen beim Scannen von Bohnen findet, konstruiert er ein Proxy -Objekt dynamisch.
Diese Annotation ist gültig, wenn Sie die A -Methode mit Annotation direkt über ein Objekt der Klasse X aufrufen möchten. Da die Spring zu diesem Zeitpunkt feststellt, dass die Methode, die Sie aufrufen möchten, eine AOP -Annotation vorliegt, und dann das Proxy -Objekt der Klasse X verwendet, um die Methode A aufzurufen.
Nehmen wir jedoch an, dass die Methode A in der Klasse X die Methode B mit Annotation aufruft, und Sie möchten die Methode A durch das Objekt der Klasse X aufrufen, dann ist die Annotation auf Methode B ungültig. Da der Frühling feststellt, dass das A You Call keine Annotation hat, wird das ursprüngliche Objekt immer noch verwendet und nicht das Proxy -Objekt. Wenn A als nächstes aufruft, ist die Annotation der Methode B im ursprünglichen Objekt natürlich ungültig.
Lösung:
Der einfachste Weg ist natürlich, Methoden A und B keine Abhängigkeiten zu haben und die Methode B direkt über Objekt der Klasse X aufzurufen.
Aber oft ist unsere Logik auf diese Weise möglicherweise nicht gut geschrieben, daher gibt es eine andere Methode: Finden Sie einen Weg, um das Proxy -Objekt manuell zu erhalten.
Die AOPContext -Klasse hat eine CurrentProxy () -Methode, mit der das Proxy -Objekt der aktuellen Klasse direkt abgerufen werden kann. Dann kann das obige Beispiel so gelöst werden:
// Aufrufmethode B in der Methode A // 1. Ruf B direkt, die Annotation ist ungültig. B () // 2. Holen Sie sich das Objekt der Proxy -Klasse und rufen Sie B. ((x) aopcontext.currentProxy ()). B () auf. B ().
Das Objekt @autowired ist in der AOP -Annotationsmethode null
In der vorherigen Verwendung wurde bei der Annotationsmethode bei Verwendung anderer injizierter Objekte festgestellt, dass das Objekt nicht injiziert wurde und es null war.
Schließlich wurde festgestellt, dass der Grund dafür darin bestand, dass die Methode privat war. Da Spring JDK Dynamic Proxy oder CGGLIB Dynamic Proxy verwendet, ist eine Klasse, die die Schnittstelle implementiert, und der andere wird durch Unterklassen implementiert. Weder die Schnittstelle noch die übergeordnete Klasse können die private Methode vorhanden sein, ansonsten können weder die Unterklasse noch die Implementierungsklasse überschrieben werden.
Wenn die Methode privat ist, kann diese Methode im Proxy -Prozess nicht gefunden werden, was zu Problemen bei der Erstellung von Proxy -Objekten und dazu führt, dass einige Objekte nicht injiziert werden.
Wenn die Methode AOP-Anmerkungen verwenden muss, stellen Sie sie auf eine nicht private Methode ein.
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.