Ich bin neu bei Spring Transaction. Etwas, das ich wirklich seltsam fand, wahrscheinlich habe ich das richtig verstanden.
Ich wollte eine Transaktion auf Methodenebene haben und ich habe eine Aufrufermethode innerhalb derselben Klasse und es scheint, dass es nicht so ist, es muss von der separaten Klasse aufgerufen werden. Ich verstehe nicht, wie das möglich ist.
Wenn jemand eine Idee hat, wie dieses Problem behoben werden kann, würde ich mich sehr freuen. Ich möchte dieselbe Klasse verwenden, um die mit Anmerkungen versehene Transaktionsmethode aufzurufen.
Hier ist der Code:
public class UserService {
@Transactional
public boolean addUser(String userName, String password) {
try {
// call DAO layer and adds to database.
} catch (Throwable e) {
TransactionAspectSupport.currentTransactionStatus()
.setRollbackOnly();
}
}
public boolean addUsers(List<User> users) {
for (User user : users) {
addUser(user.getUserName, user.getPassword);
}
}
}
java
spring
aspectj
spring-aop
Mike
quelle
quelle
TransactionTemplate
Ansatz an: stackoverflow.com/a/52989925/355438Antworten:
Dies ist eine Einschränkung von Spring AOP (dynamische Objekte und cglib ).
Wenn Sie Spring so konfigurieren, dass AspectJ zur Abwicklung der Transaktionen verwendet wird, funktioniert Ihr Code.
Die einfache und wahrscheinlich beste Alternative besteht darin, Ihren Code umzugestalten. Zum Beispiel eine Klasse, die Benutzer behandelt, und eine, die jeden Benutzer verarbeitet. Dann funktioniert die Standardtransaktionsbehandlung mit Spring AOP.
Konfigurationstipps für die Abwicklung von Transaktionen mit AspectJ
Damit Spring AspectJ für Transaktionen verwenden kann, müssen Sie den Modus auf AspectJ einstellen:
Wenn Sie Spring mit einer älteren Version als 3.0 verwenden, müssen Sie dies auch zu Ihrer Spring-Konfiguration hinzufügen:
quelle
Das Problem hierbei ist, dass die AOP-Proxys von Spring nicht erweitert werden, sondern Ihre Dienstinstanz umschließen, um Anrufe abzufangen. Dies hat zur Folge, dass jeder Aufruf von "this" innerhalb Ihrer Dienstinstanz direkt auf dieser Instanz aufgerufen wird und vom Wrapping-Proxy nicht abgefangen werden kann (der Proxy ist sich eines solchen Aufrufs nicht einmal bewusst). Eine Lösung ist bereits erwähnt. Eine weitere gute Möglichkeit wäre, Spring einfach eine Instanz des Dienstes in den Dienst selbst einfügen zu lassen und Ihre Methode für die injizierte Instanz aufzurufen, die der Proxy ist, der Ihre Transaktionen verarbeitet. Beachten Sie jedoch, dass dies auch schlimme Nebenwirkungen haben kann, wenn Ihre Service-Bean kein Singleton ist:
quelle
UserService
Singleton-Bereich hat? Was ist, wenn es dasselbe Objekt ist?Mit Spring 4 ist es möglich, sich selbst zu verdrahten
quelle
Ab Java 8 gibt es eine andere Möglichkeit, die ich aus den folgenden Gründen bevorzuge:
Dieser Ansatz hat folgende Vorteile:
1) Es kann auf private Methoden angewendet werden. Sie müssen die Kapselung also nicht unterbrechen, indem Sie eine Methode veröffentlichen, um die Spring-Einschränkungen zu erfüllen.
2) Dieselbe Methode kann innerhalb unterschiedlicher Transaktionsausbreitung aufgerufen werden, und es ist Sache des Aufrufers , die geeignete auszuwählen. Vergleichen Sie diese 2 Zeilen:
3) Es ist explizit und somit besser lesbar.
quelle
TransactionHandler
als Unterklasse erweitere und die Unterklasse diese beiden Methoden in der Superklasse aufruftTransactionHandler
, kann ich dann trotzdem die@Transactional
beabsichtigten Vorteile nutzen ?Dies ist meine Lösung für den Selbstaufruf :
quelle
Sie können BeanFactory innerhalb derselben Klasse automatisch verdrahten und a
getBean(YourClazz.class)
Es wird Ihre Klasse automatisch proximieren und Ihre @ Transactional- oder andere aop-Annotation berücksichtigen.
quelle
Das Problem hängt damit zusammen, wie Federbelastungsklassen und Proxys. Es wird nicht funktionieren, bis Sie Ihre innere Methode / Transaktion in eine andere Klasse schreiben oder zu einer anderen Klasse gehen und dann wieder zu Ihrer Klasse kommen und dann die innere verschachtelte Transkationsmethode schreiben.
Zusammenfassend lässt sich sagen, dass Spring Proxys die Szenarien, mit denen Sie konfrontiert sind, nicht zulassen. Sie müssen die 2. Transaktionsmethode in eine andere Klasse schreiben
quelle
Folgendes mache ich für kleine Projekte mit nur geringfügiger Verwendung von Methodenaufrufen innerhalb derselben Klasse. In-Code-Dokumentation wird dringend empfohlen, da sie für Kollegen seltsam aussehen kann. Aber es funktioniert mit Singletons , ist leicht zu testen, einfach, schnell zu erreichen und erspart mir die volle AspectJ-Instrumentierung. Für eine stärkere Nutzung würde ich jedoch die AspectJ-Lösung empfehlen, wie in der Antwort von Espens beschrieben.
quelle