Spring のポイントカット API
このセクションでは、Spring が重要なポイントカットの概念をどのように処理するかについて説明します。
概念
Spring のポイントカットモデルは、アドバイス型に関係なくポイントカットの再利用を可能にします。同じポイントカットで異なるアドバイスをターゲットにすることができます。
org.springframework.aop.Pointcut
インターフェースは中心的なインターフェースであり、アドバイスを特定のクラスとメソッドに向けるために使用されます。完全なインターフェースは次のとおりです。
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
Pointcut
インターフェースを 2 つの部分に分割すると、クラスとメソッドのマッチング部分ときめの細かい構成操作(別のメソッドマッチャーとの「結合」の実行など)を再利用できます。
ClassFilter
インターフェースは、ポイントカットを特定のターゲットクラスのセットに制限するために使用されます。matches()
メソッドが常に true を返す場合、すべてのターゲットクラスが一致します。次のリストは、ClassFilter
インターフェース定義を示しています。
public interface ClassFilter {
boolean matches(Class clazz);
}
通常、MethodMatcher
インターフェースの方が重要です。完全なインターフェースは次のとおりです。
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
matches(Method, Class)
メソッドは、このポイントカットがターゲットクラスの特定のメソッドと一致するかどうかをテストするために使用されます。この評価は、AOP プロキシが作成されるときに実行でき、すべてのメソッド呼び出しでのテストの必要性を回避できます。2 つの引数を持つ matches
メソッドが指定されたメソッドに対して true
を返し、MethodMatcher に対する isRuntime()
メソッドが true
を返す場合、3 つの引数の一致メソッドがすべてのメソッド呼び出しで呼び出されます。これにより、ポイントカットは、ターゲットアドバイスが開始する直前にメソッド呼び出しに渡された引数を確認できます。
ほとんどの MethodMatcher
実装は静的です。つまり、isRuntime()
メソッドは false
を返します。この場合、引数が 3 つの matches
メソッドは呼び出されません。
可能であれば、ポイントカットを静的にし、AOP フレームワークが AOP プロキシの作成時にポイントカット評価の結果をキャッシュできるようにします。 |
ポイントカットの操作
Spring は、ポイントカットの操作(特に、ユニオンとインターセクション)をサポートします。
Union は、どちらかのポイントカットが一致するメソッドを意味します。交差とは、両方のポイントカットが一致する方法を意味します。通常、Union はより便利です。org.springframework.aop.support.Pointcuts
クラスの静的メソッドを使用するか、同じパッケージの ComposablePointcut
クラスを使用して、ポイントカットを作成できます。ただし、AspectJ ポイントカット式の使用は、通常、より簡単なアプローチです。
AspectJ 式ポイントカット
2.0 以降、Spring が使用する最も重要な型のポイントカットは org.springframework.aop.aspectj.AspectJExpressionPointcut
です。これは、AspectJ が提供するライブラリを使用して AspectJ ポイントカット式文字列を解析するポイントカットです。
サポートされている AspectJ ポイントカットプリミティブについては、前の章を参照してください。
便利なポイントカットの実装
Spring はいくつかの便利なポイントカット実装を提供します。それらのいくつかを直接使用できます。その他は、アプリケーション固有のポイントカットでサブクラス化されることを目的としています。
静的ポイントカット
静的ポイントカットはメソッドとターゲットクラスに基づいており、メソッドの引数を考慮することはできません。ほとんどの場合、静的ポイントカットで十分であり、最適です。Spring は、メソッドが最初に呼び出されたときに、静的ポイントカットを一度だけ評価できます。その後、各メソッド呼び出しでポイントカットを再度評価する必要はありません。
このセクションの残りの部分では、Spring に含まれる静的ポイントカット実装のいくつかについて説明します。
正規表現のポイントカット
静的ポイントカットを指定する明白な方法の 1 つは、正規表現です。Spring 以外のいくつかの AOP フレームワークがこれを可能にします。org.springframework.aop.support.JdkRegexpMethodPointcut
は、JDK の正規表現サポートを使用する汎用正規表現ポイントカットです。
JdkRegexpMethodPointcut
クラスを使用すると、パターン文字列のリストを提供できます。これらのいずれかが一致する場合、ポイントカットは true
に評価されます。(結果として、結果として生じるポイントカットは、指定されたパターンの結合になります。)
次の例は、JdkRegexpMethodPointcut
の使用方法を示しています。
Java
Kotlin
XML
@Configuration
public class JdkRegexpConfiguration {
@Bean
public JdkRegexpMethodPointcut settersAndAbsquatulatePointcut() {
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns(".*set.*", ".*absquatulate");
return pointcut;
}
}
@Configuration
class JdkRegexpConfiguration {
@Bean
fun settersAndAbsquatulatePointcut() = JdkRegexpMethodPointcut().apply {
setPatterns(".*set.*", ".*absquatulate")
}
}
<bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
Spring は、RegexpMethodPointcutAdvisor
という名前の便利なクラスを提供します。これにより、Advice
を参照することもできます(Advice
は、アドバイスの前、インターセプト、スローなど)。バックグラウンドでは、Spring は JdkRegexpMethodPointcut
を使用しています。RegexpMethodPointcutAdvisor
を使用すると、次の例に示すように、1 つの Bean がポイントカットとアドバイスの両方をカプセル化するため、接続が簡単になります。
Java
Kotlin
XML
@Configuration
public class RegexpConfiguration {
@Bean
public RegexpMethodPointcutAdvisor settersAndAbsquatulateAdvisor(Advice beanNameOfAopAllianceInterceptor) {
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();
advisor.setAdvice(beanNameOfAopAllianceInterceptor);
advisor.setPatterns(".*set.*", ".*absquatulate");
return advisor;
}
}
@Configuration
class RegexpConfiguration {
@Bean
fun settersAndAbsquatulateAdvisor(beanNameOfAopAllianceInterceptor: Advice) = RegexpMethodPointcutAdvisor().apply {
advice = beanNameOfAopAllianceInterceptor
setPatterns(".*set.*", ".*absquatulate")
}
}
<bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
RegexpMethodPointcutAdvisor
は、任意の Advice
型で使用できます。
動的ポイントカット
動的ポイントカットは、静的ポイントカットよりも評価にコストがかかります。メソッドの引数と静的情報を考慮します。これは、すべてのメソッド呼び出しで評価する必要があり、引数が異なるため結果をキャッシュできないことを意味します。
主な例は、control flow
ポイントカットです。
制御フローポイントカット
Spring 制御フローポイントカットは、概念的には AspectJ cflow
ポイントカットに似ていますが、強力ではありません。(現在、ポイントカットが別のポイントカットと一致するジョインポイントで実行されるように指定する方法はありません)制御フローポイントカットは、現在の呼び出しスタックと一致します。例: com.mycompany.web
パッケージのメソッドまたは SomeCaller
クラスによってジョインポイントが呼び出された場合に発生する可能性があります。制御フローポイントカットは、org.springframework.aop.support.ControlFlowPointcut
クラスを使用して指定されます。
制御フローのポイントカットは、他の動的なポイントカットよりも、実行時に評価するのに非常に費用がかかります。Java 1.4 では、コストは他の動的ポイントカットの約 5 倍です。 |
ポイントカットスーパークラス
Spring は、独自のポイントカットを実装するのに役立つ便利なポイントカットスーパークラスを提供します。
静的ポイントカットは最も有用であるため、おそらく StaticMethodMatcherPointcut
をサブクラス化する必要があります。これには、抽象メソッドを 1 つだけ実装する必要があります(ただし、他のメソッドをオーバーライドして動作をカスタマイズできます)。次の例は、StaticMethodMatcherPointcut
をサブクラス化する方法を示しています。
Java
Kotlin
class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// return true if custom criteria match
}
}
class TestStaticPointcut : StaticMethodMatcherPointcut() {
override fun matches(method: Method, targetClass: Class<*>): Boolean {
// return true if custom criteria match
}
}
動的ポイントカット用のスーパークラスもあります。任意のアドバイス型でカスタムポイントカットを使用できます。
カスタムポイントカット
Spring AOP のポイントカットは(AspectJ のような)言語機能ではなく Java クラスであるため、静的または動的にかかわらず、カスタムポイントカットを宣言できます。Spring のカスタムポイントカットは、任意に複雑にすることができます。ただし、可能であれば、AspectJ ポイントカット式言語の使用をお勧めします。
Spring の以降のバージョンは、JAC が提供する「セマンティックポイントカット」のサポートを提供する可能性があります。たとえば、「ターゲットオブジェクトのインスタンス変数を変更するすべてのメソッド」です。 |