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

1. Übersicht

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

Wir werden zunächst einige Begriffe einführen, die in der aspektorientierten Programmierung verwendet werden. Ein Join-Punkt ist ein Schritt der Programmausführung, z. B. die Ausführung einer Methode oder die Behandlung einer Ausnahme. In Spring AOP repräsentiert ein Join-Punkt immer eine Methodenausführung. Ein Pointcut ist ein Prädikat, das mit den Verknüpfungspunkten übereinstimmt, und eine Pointcut-Ausdruckssprache ist eine Möglichkeit, Pointcuts programmgesteuert zu beschreiben.

2. Verwendung

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

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

Die Methodendeklaration wird als Pointcut-Signatur bezeichnet . Es enthält einen Namen, der von Hinweisanmerkungen verwendet werden kann, um auf diesen Punktschnitt zu verweisen.

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

Ein Pointcut-Ausdruck kann auch als Wert der Ausdruckseigenschaft eines aop: pointcut- Tags angezeigt werden :

3. Pointcut-Bezeichner

Ein Pointcut-Ausdruck beginnt mit einem Pointcut-Bezeichner (Pointcut Designator, PCD) , einem Schlüsselwort, das Spring AOP mitteilt, was übereinstimmen soll. Es gibt mehrere Pointcut-Bezeichner, z. B. die Ausführung einer Methode, eines Typs, Methodenargumente oder Anmerkungen.

3.1 Ausführung

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

@Pointcut("execution(public String com.baeldung.pointcutadvice.dao.FooDao.findById(Long))")

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

@Pointcut("execution(* com.baeldung.pointcutadvice.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 innerhalb

Eine weitere Möglichkeit , um das gleiche Ergebnis aus dem vorherigen Abschnitt zu erreichen , wird durch die Verwendung von im PCD, die Grenzen Einstimmungspunkte bestimmter Typen zu verbinden.

@Pointcut("within(com.baeldung.pointcutadvice.dao.FooDao)")

Wir könnten auch jedem Typ innerhalb des com.baeldung- Pakets oder eines Unterpakets entsprechen .

@Pointcut("within(com.baeldung..*)")

3.3 dies und Ziel

Dies begrenzt die Übereinstimmung mit Verknüpfungspunkten, bei denen die Bean-Referenz eine Instanz des angegebenen Typs ist, während das Ziel 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 Ziel- PCD verwenden, da das Proxy-Objekt eine Instanz der Proxy- Klasse ist und die BarDao- Schnittstelle implementiert :

@Pointcut("target(com.baeldung.pointcutadvice.dao.BarDao)")

Wenn FooDao hingegen keine Schnittstelle implementiert oder die Eigenschaft proxyTargetClass auf true gesetzt ist, ist das Proxy-Objekt eine Unterklasse von FooDao, und diese PCD kann verwendet werden:

@Pointcut("this(com.baeldung.pointcutadvice.dao.FooDao)")

3,4 Argumente

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 Typ Long hat . Wenn wir eine Methode mit einer beliebigen Anzahl von Parametern abgleichen möchten, aber den ersten Parameter vom Typ Long haben , können wir den folgenden Ausdruck verwenden:

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

3.5 @target

Die @ Ziel- PCD (nicht zu verwechseln mit der oben beschriebenen Ziel- PCD) beschränkt die Übereinstimmung auf Verknüpfungspunkte, an denen die Klasse des ausführenden Objekts eine Anmerkung des angegebenen Typs enthält:

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

3.6 @args

Diese PCD beschränkt die Übereinstimmung auf Verknüpfungspunkte, an denen der Laufzeittyp der tatsächlich übergebenen Argumente Anmerkungen des angegebenen Typs (der angegebenen Typen) enthält. Angenommen, wir möchten alle Methoden verfolgen, die mit @ Annity Annotation annotierte Beans akzeptieren :

@Pointcut("@args(com.baeldung.pointcutadvice.annotations.Entity)") public void methodsAcceptingEntities() {}

Um auf das Argument zuzugreifen, sollten wir dem Rat ein JoinPoint- Argument hinzufügen :

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

3.7 @in

Diese PCD beschränkt die Übereinstimmung auf Verknüpfungspunkte innerhalb von 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 auf Verknüpfungspunkte, bei denen das Thema des Verknüpfungspunkts die angegebene Anmerkung enthält. Zum Beispiel können wir eine @ Loggable- Annotation erstellen :

@Pointcut("@annotation(com.baeldung.pointcutadvice.annotations.Loggable)") public void loggableMethods() {}

Dann können wir die Ausführung der durch diese 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 && , || kombiniert werden und ! Betreiber:

@Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {} @Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {} @Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {}

5. Schlussfolgerung

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 auf GitHub.