春のポイントカット式の紹介
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ベースのプロジェクトなので、インポートは簡単です。そのまま実行します。