1概要

このチュートリアルでは、Spring AOPのポイントカット式言語について説明します。

まずアスペクト指向プログラミングで使用される用語をいくつか紹介します。結合点は、メソッドの実行や例外の処理など、プログラム実行のステップです。 Spring AOPでは、ジョインポイントは常にメソッドの実行を表します。

pointcut

は結合点に一致する述語で、

pointcut式language

はプログラムでポイントカットを記述するための方法です。


2使用法

ポイントカット式は、

@ Pointcut

アノテーションの値として表示できます。

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

メソッド宣言は

pointcutシグニチャ

と呼ばれます。それはそのポイントカットを参照するためにアドバイスアノテーションによって使われることができる名前を提供します。

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

ポイントカット式は、

aop:pointcut

タグの

expression

プロパティの値としても表示できます。

<aop:config>
    <aop:pointcut id="anyDaoMethod"
      expression="@target(org.springframework.stereotype.Repository)"/>
</aop:config>


3ポイントカット指定子

ポイントカット式は、ポイントカット指定子(PCD)** で始まります。これは、Spring AOPに何を一致させるかを指示するキーワードです。メソッドの実行、型、メソッドの引数、注釈など、いくつかのポイントカット指示子があります。


3.1

実行


プライマリSpring PCDは

execution

で、これはメソッド実行のジョインポイントと一致します。

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

このポイントカットの例は、

FooDao

クラスの

findById

メソッドの実行と完全に一致します。これはうまくいきますが、それほど柔軟ではありません。


FooDao

クラスのすべてのメソッドを一致させたいとします。これらのメソッドは、異なる署名、戻り値の型、および引数を持つことができます。これを実現するために、ワイルドカードを使用することができます。

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

ここで、最初のワイルドカードは任意の戻り値に一致し、2番目のワイルドカードは任意のメソッド名に一致し、

(..)

パターンは任意の数のパラメーター(ゼロ以上)に一致します。


3.2

within


前のセクションと同じ結果を得るための別の方法は

within

PCDを使うことです。

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


org.baeldung

パッケージまたはサブパッケージ内の任意の型に一致させることもできます。

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


3.3

this



target



this

は、Bean参照が特定の型のインスタンスであるジョインポイントへのマッチングを制限し、

target

は、ターゲットオブジェクトが特定の型のインスタンスであるジョインポイントへのマッチングを制限します。前者はSpring AOPがCGLIBベースのプロキシを作成するときに機能し、後者はJDKベースのプロキシが作成されるときに使用されます。ターゲットクラスがインタフェースを実装しているとします。

public class FooDao implements BarDao {
    ...
}

この場合、Spring AOPはJDKベースのプロキシを使用します。プロキシされたオブジェクトは

Proxy

クラスのインスタンスであり、

BarDao

インタフェースを実装するため、

target

PCDを使用する必要があります。

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

一方、

FooDao

がインターフェイスを実装していない場合、または

proxyTargetClass

プロパティがtrueに設定されている場合、プロキシオブジェクトは

FooDao

のサブクラスとなり、

this

PCDを使用できます。

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


3.4

args


このPCDは、特定のメソッド引数を照合するために使用されます。

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

このポイントカットは、findで始まり、

Long

型のパラメータが1つだけのメソッドに一致します。メソッドを

Long

型のfistパラメータを持つ任意の数のパラメータと一致させる場合は、次の式を使用できます。

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


3.5

@ target



@ target

PCD(上記の

target

PCDと混同しないでください)は、実行中のオブジェクトのクラスが与えられた型の注釈を持つジョインポイントへのマッチングを制限します。

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


3.6

@ args


このPCDは、渡された実引数のランタイム型が指定された型の注釈を持つジョインポイントへのマッチングを制限します。

@ Entity

アノテーションが付けられたBeanを受け入れるすべてのメソッドをトレースしたいとします。

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

引数にアクセスするには、アドバイスに

JoinPoint

引数を指定します。

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


3.7

@ within


このPCDは、与えられた注釈を持つ型の中の結合点へのマッチングを制限します。

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

これは以下と同等です。

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


3.8

@アノテーション


このPCDは、結合点の件名に与えられた注釈がある結合点へのマッチングを制限します。たとえば、

@ Loggable

アノテーションを作成します。

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

それから、そのアノテーションによってマークされたメソッドの実行を記録するかもしれません:

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


4ポイントカット式を組み合わせる

ポイントカット式は** を使って組み合わせることができます。

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

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

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


5結論

Spring AOPとポイントカットの簡単な紹介では、ポイントカット式の使用例をいくつか示しました。

例のフルセットはhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-java[my github project]にあります – これはEclipseベースのプロジェクトなので、インポートは簡単です。そのまま実行します。