Einführung in Pointcut-Ausdrücke im Frühling

Einführung in Pointcut-Ausdrücke im Frühjahr

1. Überblick

In diesem Tutorial werden wir die Pointcut-Ausdruckssprache von Spring AOP diskutieren.

Wir werden zunächst einige Begriffe einführen, die in der aspektorientierten Programmierung verwendet werden. Ajoin point ist ein Schritt der Programmausführung, z. B. die Ausführung einer Methode oder die Behandlung einer Ausnahme. In Spring AOP repräsentiert ein Verknüpfungspunkt immer eine Methodenausführung. Einpointcut ist ein Prädikat, das mit den Verbindungspunkten übereinstimmt, und einpointcut expression language ist eine Methode zur programmgesteuerten Beschreibung von Punktschnitten.

2. Verwendungszweck

Ein Pointcut-Ausdruck kann als Wert der Annotation@Pointcutangezeigt werden:

@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryClassMethods() {}

Die Methodendeklaration heißtpointcut signature. Es gibt einen Namen an, der von Hinweisanmerkungen verwendet werden kann, um auf diesen Pointcut zu verweisen.

@Around("repositoryClassMethods()")
public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
    ...
}

Ein Pointcut-Ausdruck kann auch als Wert derexpression-Eigenschaft einesaop:pointcut-S-Tags angezeigt werden:


    

3. Pointcut-Bezeichner

Ein Pointcut-Ausdruck beginnt mitpointcut designator (PCD). Dies ist ein Schlüsselwort, das Spring AOP mitteilt, was übereinstimmen soll. Es gibt verschiedene Pointcut-Bezeichner, z. B. die Ausführung einer Methode, einen Typ, Methodenargumente oder Anmerkungen.

3.1 execution

Die primäre Spring-PCD istexecution, was den Verbindungspunkten für die Methodenausführung entspricht.

@Pointcut("execution(public String org.example.dao.FooDao.findById(Long))")

Dieser Beispielpunktschnitt entspricht genau der Ausführung der MethodefindByIdder KlasseFooDao. Das funktioniert, ist aber nicht sehr flexibel. Angenommen, wir möchten alle Methoden derFooDao-Klasse abgleichen, die unterschiedliche Signaturen, Rückgabetypen und Argumente haben können. Um dies zu erreichen, können wir Platzhalter verwenden:

@Pointcut("execution(* org.example.dao.FooDao.*(..))")

Hier stimmt der erste Platzhalter mit einem beliebigen Rückgabewert überein, der zweite mit einem beliebigen Methodennamen und das(..)-Muster mit einer beliebigen Anzahl von Parametern (null oder mehr).

3.2 within

Eine andere Möglichkeit, das gleiche Ergebnis aus dem vorherigen Abschnitt zu erzielen, ist die Verwendung der PCDwithin, die die Übereinstimmung mit Verbindungspunkten bestimmter Typen einschränkt.

@Pointcut("within(org.example.dao.FooDao)")

Wir könnten auch jeden Typ innerhalb desorg.example-Pakets oder eines Unterpakets abgleichen.

@Pointcut("within(org.example..*)")

3.3 this and target

this begrenzt die Übereinstimmung mit Verknüpfungspunkten, bei denen die Bean-Referenz eine Instanz des angegebenen Typs ist, währendtarget die Übereinstimmung mit Verknüpfungspunkten begrenzt, bei denen das Zielobjekt eine Instanz des angegebenen Typs ist. Ersteres funktioniert, wenn Spring AOP einen CGLIB-basierten Proxy erstellt, und letzteres wird verwendet, wenn ein JDK-basierter Proxy erstellt wird. Angenommen, die Zielklasse implementiert eine Schnittstelle:

public class FooDao implements BarDao {
    ...
}

In diesem Fall verwendet Spring AOP den JDK-basierten Proxy, und Sie sollten die PCDtargetverwenden, da das Proxy-Objekt eine Instanz der KlasseProxyist, und die SchnittstelleBarDaoimplementieren:

@Pointcut("target(org.example.dao.BarDao)")

Wenn andererseitsFooDao keine Schnittstelle implementiert oder die EigenschaftproxyTargetClassauf true gesetzt ist, ist das Proxy-Objekt eine Unterklasse vonFooDao und die PCD vonthis könnte verwendet werden:

@Pointcut("this(org.example.dao.FooDao)")

3.4 args

Diese PCD wird zum Abgleichen bestimmter Methodenargumente verwendet:

@Pointcut("execution(* *..find*(Long))")

Dieser Pointcut entspricht jeder Methode, die mit find beginnt und nur einen Parameter vom TypLong enthält. Wenn wir eine Methode mit einer beliebigen Anzahl von Parametern abgleichen möchten, aber den ersten Parameter vom TypLong haben, können wir den folgenden Ausdruck verwenden:

@Pointcut("execution(* *..find*(Long,..))")

3.5 @target

Die@target-PCD (nicht zu verwechseln mit der oben beschriebenentarget-PCD) begrenzt die Übereinstimmung mit Verbindungspunkten, an denen die Klasse des ausführenden Objekts eine Anmerkung des angegebenen Typs aufweist:

@Pointcut("@target(org.springframework.stereotype.Repository)")

3.6 @args

Diese PCD beschränkt die Übereinstimmung mit Verknüpfungspunkten, an denen der Laufzeittyp der tatsächlich übergebenen Argumente Anmerkungen des angegebenen Typs enthält. Angenommen, wir möchten alle Methoden verfolgen, die Beans akzeptieren, die mit@Entity Annotation versehen sind:

@Pointcut("@args(org.example.aop.annotations.Entity)")
public void methodsAcceptingEntities() {}

Um auf das Argument zuzugreifen, sollten wir dem Rat einJoinPoint-Argument geben:

@Before("methodsAcceptingEntities()")
public void logMethodAcceptionEntityAnnotatedBean(JoinPoint jp) {
    logger.info("Accepting beans with @Entity annotation: " + jp.getArgs()[0]);
}

3.7 @within

Diese PCD beschränkt die Übereinstimmung mit Verknüpfungspunkten in Typen mit der angegebenen Anmerkung:

@Pointcut("@within(org.springframework.stereotype.Repository)")

Welches ist gleichbedeutend mit:

@Pointcut("within(@org.springframework.stereotype.Repository *)")

3.8 @annotation

Diese PCD beschränkt die Übereinstimmung mit Verbindungspunkten, bei denen der Betreff des Verbindungspunkts die angegebene Anmerkung aufweist. Zum Beispiel können wir eine@Loggable-Annotation erstellen:

@Pointcut("@annotation(org.example.aop.annotations.Loggable)")
public void loggableMethods() {}

Dann können wir die Ausführung der mit dieser Annotation gekennzeichneten Methoden protokollieren:

@Before("loggableMethods()")
public void logMethod(JoinPoint jp) {
    String methodName = jp.getSignature().getName();
    logger.info("Executing method: " + methodName);
}

4. Kombinieren von Pointcut-Ausdrücken

Pointcut-Ausdrücke können mit den Operatoren&&,|| und! kombiniert werden:

@Pointcut("@target(org.springframework.stereotype.Repository)")
public void repositoryMethods() {}

@Pointcut("execution(* *..create*(Long,..))")
public void firstLongParamMethods() {}

@Pointcut("repositoryMethods() && firstLongParamMethods()")
public void entityCreationMethods() {}

5. Fazit

In dieser kurzen Einführung in Spring AOP und Pointcuts haben wir einige Beispiele für die Verwendung von Pointcut-Ausdrücken veranschaulicht.

Die vollständigen Beispiele finden Sie inmy github project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.