Frage

Ich möchte wissen, was tatsächlich passiert, wenn Sie eine Methode mit Anmerkungsanträgen mit @Transactional? Natürlich weiß ich, dass die Frühling diese Methode in eine Transaktion einpackt.

Aber ich habe die folgenden Zweifel:

  1. Ich habe gehört, dass der Frühling eine schafft Proxy -Klasse? Kann jemand dies mehr erklären Tiefe. Was liegt eigentlich in dieser Proxy -Klasse? Was passiert mit der eigentlichen Klasse? Und wie kann ich die erstellte Proxied -Klasse von Spring sehen
  2. Ich habe auch in Frühjahrsdokumenten gelesen:

Hinweis: Da dieser Mechanismus auf Proxies basiert, basiert Nur "externe" Methodenaufrufe, die durch den Stellvertreter eingehen, werden abgefangen. Dies bedeutet, dass "Selbstverlebung", dh eine Methode innerhalb des Zielobjekts, die eine andere Methode des Zielobjekts aufruft, nicht zur Laufzeit zu einer tatsächlichen Transaktion führt @Transactional!

Quelle: http://static.springource.org/spring/docs/2.0.x/reference/transaction.html

Warum werden nur externe Methodenaufrufe unter Transaktion und nicht in den selbstverlangenden Methoden stehen?

War es hilfreich?

Lösung

Dies ist ein großes Thema. Das Spring Reference DOC widmet ihm mehrere Kapitel. Ich empfehle, die zu lesen Aspekt-orientiertes Programmieren und Transaktionen, wie die deklarative Transaktionsunterstützung von Spring bei seiner Stiftung AOP verwendet.

Aber auf einem sehr hohen Niveau schafft Spring Proxies für Klassen, die deklarieren @Transactional auf der Klasse selbst oder auf Mitgliedern. Der Proxy ist zur Laufzeit größtenteils unsichtbar. Es bietet eine Möglichkeit für den Frühling, Verhaltensweisen vor, nach oder um Methodenaufrufe zu injizieren. Das Transaktionsmanagement ist nur ein Beispiel für die Verhaltensweisen, die angeschlossen werden können. Sicherheitsüberprüfungen sind ein anderer. Und Sie können auch Ihre eigenen für Dinge wie Protokollierung zur Verfügung stellen. Also, wenn Sie eine Methode mit Anmerkungen mit Anmerkungen mit @Transactional, Frühling erstellt dynamisch einen Proxy, der dieselbe Schnittstelle (en) wie die Klasse, die Sie annotieren, implementiert. Und wenn Clients Anrufe in Ihr Objekt tätigen, werden die Anrufe abgefangen und das Verhalten über den Proxy -Mechanismus injiziert.

Transaktionen in EJB funktionieren übrigens ähnlich.

Wie Sie beobachtet haben, funktioniert der Proxy -Mechanismus nur, wenn Anrufe von einem externen Objekt stammen. Wenn Sie im Objekt einen internen Anruf tätigen, tätigen Sie wirklich einen Anruf durch das "Dies"Referenz, die den Proxy umgeht. Es gibt jedoch Möglichkeiten, dieses Problem zu umgehen. Ich erkläre einen Ansatz in Dieser Forum Post in dem ich a benutze BeanfactoryPostProcessor Einen Instanz des Proxy in "Selbstreferenz" -Kurse zur Laufzeit injizieren. Ich speichere diese Referenz auf eine Mitgliedsvariable namens "mich". Wenn ich dann interne Anrufe tätigen muss, die eine Änderung des Transaktionsstatus des Threads erfordern, leite ich den Anruf über den Proxy (z."me.somemethod ()".) Der Forum -Beitrag erklärt ausführlicher. Beachten Sie, dass die BeanfactoryPostProcessor Der Code wäre jetzt etwas anders, da er im Frühjahr 1.x -Zeitrahmen geschrieben wurde. Aber hoffentlich gibt es dir eine Idee. Ich habe eine aktualisierte Version, die ich wahrscheinlich zur Verfügung stellen könnte.

Andere Tipps

Wenn Spring Ihre Bean -Definitionen lädt und so konfiguriert wurde, dass sie nach @Transactional -Anmerkungen suchen, werden diese Proxy -Objekte um Ihre tatsächliche Bohne erstellt. Diese Proxy-Objekte sind Fälle von Klassen, die zur Laufzeit automatisch generiert werden. Das Standardverhalten dieser Proxy -Objekte, wenn eine Methode aufgerufen wird, besteht darin, dieselbe Methode auf der "Ziel" -Bohne (dh Ihre Bohne) aufzurufen.

Die Stellvertreter können jedoch auch mit Interceptors geliefert werden. Wenn diese Interceptors vorhanden sind, werden die Stellvertreter vor dem Aufrufen der Methode Ihrer Zielbean aufgerufen. Für die mit @Transactional kommentierten Zielbohnen erzeugt die Spring einen Transaktionsinterceptor und übergibt ihn an das generierte Proxy -Objekt. Wenn Sie also die Methode aus dem Client -Code aufrufen, rufen Sie die Methode im Proxy -Objekt auf, das zuerst den Transaktionsinterceptor (der eine Transaktion beginnt) aufgerufen wird, was wiederum die Methode auf Ihrer Zielbohne aufruft. Wenn der Aufruf fertig ist, verpflichtet sich der Transaktionsinterceptor die Transaktion/rollt zurück. Es ist transparent für den Client -Code.

Was die "externe Methode" betrifft, wenn Ihre Bohne eine seiner eigenen Methoden anruft, wird dies nicht über den Proxy tun. Denken Sie daran, Frühling wickelt Ihre Bohne in den Stellvertreter, Ihre Bohne hat keine Kenntnis davon. Nur Anrufe von "außerhalb" Ihrer Bohne gehen durch den Stellvertreter.

Hilft das?

Als visuelle Person wiege ich gerne mit einem Sequenzdiagramm des Proxy -Musters. Wenn Sie nicht wissen, wie Sie die Pfeile lesen, habe ich den ersten so gelesen: Client ausgeführt Proxy.method().

  1. Der Kunde nennt eine Methode auf dem Ziel aus seiner Sicht und wird vom Proxy stillschweigend abgefangen
  2. Wenn ein Vor -Aspekt definiert ist, wird der Proxy ihn ausführen
  3. Dann wird die tatsächliche Methode (Ziel) ausgeführt
  4. After-Returning und After-Throwing sind optionale Aspekte, die nach Rückgabe der Methode ausgeführt werden und/oder wenn die Methode eine Ausnahme ausgelegt hat
  5. Danach führt der Proxy den Afteraspekt aus (falls definiert)
  6. Schließlich kehrt der Proxy zum Anrufkunden zurück

Proxy Pattern Sequence Diagram(Ich durfte das Foto unter der Bedingung posten, dass ich seine Herkunft erwähnt habe. Autor: Noel Vaes, Website: www.noelvaes.eu)

Die einfachste Antwort ist, ist, Bei welcher Methode, die Sie @Transactional deklarieren, die Grenze der Transaktionsstarts und die Grenze endet, wenn die Methode abgeschlossen ist.

Wenn Sie JPA -Aufruf verwenden, befinden sich alle Commits in dieser Transaktionsgrenze. Nehmen wir an, Sie speichern Entity1, Entity2 und Entity3. Während des Speicherns von Entity3 tritt eine Ausnahme dann auf, da Enitiy1 und Entity2 in derselben Transaktion ausgestattet sind, sodass Entity1 und Entity2 mit Entity3 rollback sein werden.

Transaktion: (Entity1.Save, Entity2.Save, Entity3.Save). Jede Ausnahme führt zu einem Rollback aller JPA -Transaktionen mit DB. Die interne JPA -Transaktion wird nach Frühling verwendet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top