2015-08-17 9 views
6

Ich habe eine benutzerdefinierte Around implementiert, um auf eine benutzerdefinierte Annotation übereinstimmen. Ich möchte, dass die benutzerdefinierte Umgebung innerhalb des äußeren @Transactional ausgeführt wird. Leider scheint dies nicht zu funktionieren. (Das AOP funktioniert. Ich sehe Stacktraces, die es zeigen).Benutzerdefinierte Frühling AOP um + @Transactional

Die Stack-Traces zeigen, dass mein AOP zuvor ausgeführt wurde (ein Logger), die MyBatis-Sitzung eine Transaktion startet, MyBatis die Transaktionen schließt, Spring die Transaktion schließt und dann mein AOP beendet.

Ich dachte, mein AOP-Gerät hätte geholfen. Ich habe den Rückgabewert auf 1 gesetzt. Ich habe es benutzt. Das hat nicht funktioniert. Ich denke es liegt daran, dass ich falsch gelesen habe, wie Spring bestellt.

Beratung Bestellung

Was passiert, wenn mehrere Stücke von Beratung alle an der gleichen Stelle beitreten ausführen möchten? Spring AOP folgt den gleichen Vorrangregeln wie AspectJ, um die Reihenfolge der Ausführung von Advice zu bestimmen. Der höchste Precedence Advice wird zuerst "auf dem Weg dorthin" ausgeführt (also zwei Stücke von vor dem Rat gegeben, der mit der höchsten Priorität läuft zuerst). "Auf der Ausweg" von einem Join-Punkt, läuft die höchste Precedence Beratung letzten (so gegeben zwei Stücke von nach Beratung, die mit der höchsten Vorrang wird als zweiter laufen).

Wenn zwei Ratschläge, die in verschiedenen Aspekten definiert sind, beide am selben Join-Punkt ausführen müssen, ist die Reihenfolge nicht definiert. Sie können die Reihenfolge der Ausführung steuern, indem Sie die Priorität angeben. Dies geschieht im normalen Spring-Verfahren, indem entweder die org.springframework.core.Ordered-Schnittstelle in der Aspektklasse implementiert oder mit der Order-Annotation versehen wird. Bei zwei Aspekten hat der Aspekt, der den niedrigeren Wert von Ordered.getValue() (oder den Anmerkungswert) zurückgibt, die höhere Priorität.

Wenn zwei Ratschläge im gleichen Aspekte definiert müssen beide an den gleichen beitreten Punkt laufen, die Reihenfolge nicht definiert ist (da es kein Weg, um die Erklärung, um über Reflexion für javac-kompilierten Klassen abgerufen werden) . Ziehen Sie in Betracht, solche Beratungsmethoden in eine Beratungsmethode pro Verknüpfungspunkt in jeder Aspektklasse zu reduzieren oder die Ratschläge in separate Aspektklassen umzuwandeln - die auf der Aspektebene bestellt werden können.

Also nahm ich das Bestellattribut heraus. Dies sollte @Transactional integer.MIN_VALUE zurückgeben. Also sollte es, wenn ich das Zitat oben verstanden habe, zuletzt laufen. Wenn ich es erneut implementiert habe, wurde es immer noch rückwärts ausgeführt. Mein AOP, Spring TX, MyBatis, Schließen MyBatis, Schließen Spring Tx, Schließen Sie mein AOP.

Was mache ich falsch?

Antwort

7

Wenn die Reihenfolge Attribut nicht für @Transactional Annotation konfiguriert ist, dann ist die Advisor die für Transaktionsattribut verantwortlich ist - AbstractPointcutAdvisor (in der Tat einer der Unterklassen davon) Ordered .LOWEST_PRECEDENCE zurück, die als Integer definiert ist .MAX_WERT.

Der Advisor, der für benutzerdefinierte AOP-Beratung, eine Unterklasse desselben AbstractPointcutAdvisor, verantwortlich ist, sucht, ob die tatsächliche Advice geordnete Schnittstelle implementiert, und wenn dies der Fall ist, wird der angegebene Wert während der Sortierung verwendet. Wenn der benutzerdefinierte AOP-Hinweis die bestellte Schnittstelle nicht implementiert, gibt der Advisor den gleichen Standard Ordered.LOWEST_PRECEDENCE zurück, und das Ergebnis der Sortierung wird leicht unberechenbar.

Also konfigurieren Sie das Auftragsattribut für @ Transactional Annotation, z. wie diese

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation=" 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx-3.1.xsd> 
      ....... 

      <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="[Order for @Transactional]"> 
<beans/>  

und Implementierung kundenspezifische AOP Beratung wie diese dann

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

import org.springframework.core.Ordered; 

@Aspect 
public class CustomAspect implements Ordered { 

    @Around(value = "@annotation(CustomAnnotation)") 
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { 
    ... 
    } 
    .... 

    @Override 
    public int getOrder() { 
     return [Order for @CustomAnnotation]; 
    } 

    .... 

} 

sieht haben Sie wahrscheinlich alle Freiheiten (noch, statisch) mit der Bestellung der gesamten Anwendung.

Unter der Haube ist es AspectJAwareAdvisorAutoProxyCreator, die auf einem Proxy-Initialisierung die Berater mit dem Komparator org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator sortiert die Delegierten die zu OrderComparator Sortierung. Später, nach der tatsächlichen Ausführung, eine konkrete Implementierung von AopProxy hält für eine bestimmte Methode ein Array der Ratschläge, die es Interzeptoren nennt, und dies könnte für dynamische Neuordnung verwendet werden, denke ich, aber nichts von diesen Dingen scheint mir leicht zugänglich und/oder konfigurierbar.

Meine Umgebung ist Spring Beans, TX, AOP - alle Version 4.0.3. Ich zwei benutzerdefinierte Transaktionsmanager auch haben, ist eine Hibernate-gebunden und ist JDBC Datasource-gebunden, aber ich glaube nicht, dass hier

zählt
3

Nach ein wenig Experimentieren stellt sich heraus, dass das Entfernen des Attributs dieses nicht funktioniert. Ich finde das merkwürdig, da die @Transactional-Standardreihenfolge Integer.MIN_VALUE ist. Wenn Sie die Bestellung aktivieren möchten, müssen Sie die Bestellung explizit auf den kleinsten aller AOP-Bestellungen festlegen.

Verwandte Themen