Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
61
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

Spring AOP ポイントカット指定子の書き方について

概要

AOPのポイントカット指定子の書き方のまとめ記事になります。
なお、この記事ではAOPの詳細、Aspectの実装やアドバイスについては扱いません。別途リンクしている参考記事をご覧ください。

環境

  • Windows10 Professional
  • Java 1.8.0_131
  • Spring Boot 1.5.3
    • Spring AOP 4.3.8

参考

PointCut式

指定子

Spring AOPがサポートするAspectJのポイントカット指定子(pointcut designators)の種類。

  • execution
  • within
  • this
  • target
  • args
  • @​target
  • @​args
  • @​within
  • @​annotation
  • bean (Spring AOPの追加ポイントカット指定子)

execution

for matching method execution join points, this is the primary pointcut designator you will use when working with Spring AOP

書式

format
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
書式部 パターン 備考
modifiers-pattern 修飾子 省略化
ret-type-pattern 戻り値の型
declaring-type-pattern 宣言の型 省略化
name-pattern メソッド名
param-pattern パラメータの型
throws-pattern 例外の型 省略化
@Around("execution(public String com.example.*..*ServiceImpl.find*(String,Long,Long) throws Exception)")
                   ^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
                   |      |      |                           |    |                  |
                   |      |      |                           |    |                  +--- throws-pattern
                   |      |      |                           |    +--- param-pattern
                   |      |      |                           +--- name-pattern
                   |      |      +--- declaring-type-pattern
                   |      +--- ret-type-pattern
                   +--- modifiers-pattern

この条件は下記のクラスのfindOneメソッドにマッチします。

package com.example.service.impl;

@Service
public class EvianServiceImpl implements EvianService {

  //...省略

  public String findOne(String title, Long id, Long price) throws Exception {
    //...省略
  }

}
modifiers-pattern

修飾子を指定します。publicは省略可能です。
ただしSpring AOPではpublicメソッドのみサポートするので実質、明示的に指定する必要はありません。

例_(省略した記述)
@Around("execution(String *..*ServiceImpl.find*(String,Long,Long) throws Exception)")

Due to the proxy-based nature of Spring’s AOP framework, calls within the target object are by definition not intercepted.
For JDK proxies, only public interface method calls on the proxy can be intercepted. With CGLIB, public and protected method calls on the proxy will be intercepted, and even package-visible methods if necessary. However, common interactions through proxies should always be designed through public signatures.

ret-type-pattern

戻り値のパターンを指定します。型を明示しなくてもいい場合は"*"で記述することができます。

例_(戻り値を*で記述)
@Around("execution(* *..*ServiceImpl.find*(String,Long,Long) throws Exception)")
declaring-type-pattern

パッケージ名、クラス名のパターンを指定します。記述の通り部分一致で指定することができます。
省略可能です。

例_(省略した記述)
@Around("execution(public String find*(..) throws Exception)")
name-pattern

メソッド名のパターンを指定します。既述の通り部分一致で指定することができます。

例_(メソッド名を部分一致で記述)
find*(..)

もちろん、省略しない記述もできます。

例_(省略しない記述)
findOne(..)
param-pattern

パラメータのパターンを指定します。何通りかの記述方法がありますが特に明示する必要がなければ".."と記述することができます。

@Around("execution(* *..*ServiceImpl.find*(..) throws Exception)")

部分的に指定する場合。1番目の引数はStringで2番目以降の型は任意(引数がなくてもよい)の場合。

find*(String,..)

引数の数が決まっているが、型は決めない場合はワイルドカードで記述します。

find*(*,*,*)

引数を取らない場合。

find*()
throws-pattern

例外のパターンを指定します。名前の部分一致で指定することもできます。

@Around("execution(* *..*ServiceImpl.find*(..) throws *Exception)")

省略可能です。

@Around("execution(* *..*ServiceImpl.find*(..))")

within

limits matching to join points within certain types (simply the execution of a method declared within a matching type when using Spring AOP)

FQCNで指定するクラスのメソッドに適用します。

OK
@Around("within(com.example.service.impl.WeatherServiceImpl)")

指定するパッケージ下のクラスのメソッドに適用します。

OK
@Around("within(com.example.service.impl.*)")

指定するクラスのメソッドに適用します。

OK
@Around("within(*..WeatherServiceImpl)")

インターフェースは指定できません。

NG
@Around("within(com.example.service.WeatherService)")
public interface WeatherService {
  //...省略
}

バインディング

withinはバインディングはできません。

@​within

limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP)

'@within' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

指定するアノテーションを付与したクラスのメソッドに適用します。

OK
@Around("@within(com.example.annotation.AopWithin)")
@AopWithin
@Service
public class WeatherServiceImpl implements WeatherService {
  //...省略
}

バインディング

アノテーションをアドバイザにバインドすることができます。

OK
@Around("@within(aopWithin)")
public Object w4(ProceedingJoinPoint pjp, AopWithin aopWithin) throws Throwable {
  //...省略
}

target

limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type

'target' is more commonly used in a binding form :- see the following section on advice for how to make the target object available in the advice body.

指定するインターフェースまたは抽象クラスの実装クラスのメソッドに適用します。

OK
@Around("target(com.example.service.AbstractService)")

バインディング

インターフェースをアドバイザにバインドすることができます。

OK
@Around("target(service)")
public Object t2(ProceedingJoinPoint pjp, AbstractService service) throws Throwable {
  //...省略
}

データソースもインターフェースなので下記のようにデータソースのメソッドにも適用できます。

@Around("target(datasource)")
public Object b1(ProceedingJoinPoint pjp, DataSource datasource) throws Throwable {
  //...省略
}

@​target

limits matching to join points (the execution of methods when using Spring AOP) where the class of the executing object has an annotation of the given type

'@target' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

不明です。
調べたのですがよくわかりませんでした。

args

'args' is more commonly used in a binding form :- see the following section on advice for how to make the method arguments available in the advice body.

指定する引数を取るメソッドに適用する。
args単体で設定すると実行時エラーになったのでexecutionと併せて対象を絞っています。

この例ではWeatherFormというクラスを引数に取るメソッドに適用しています。

OK
@Around("execution(* com.example.*..*.*(..)) && args(com.example.form.WeatherForm)")

argsは指定する引数の並びが重要です。
WeatherFormの他にも引数を取る場合は、その引数を明示するか、または".."を付ける必要があります。

@Around("execution(* com.example.*..*.*(..)) && args(com.example.form.WeatherForm,..)")

バインディング

引数をアドバイザにバインドすることができます。

OK
@Around("execution(* com.example.*..*.*(..)) && args(form,..)")
public Object a2(ProceedingJoinPoint pjp, WeatherForm form) throws Throwable {
  //...省略
}

@​args

'@args' can also be used in a binding form :- see the following section on advice for how to make the annotation object(s) available in the advice body.

指定するアノテーションを付与したクラスのオブジェクトを引数に取るメソッドに適用します。

OK
@Around("execution(* com.example.*..*.*(..)) && @args(com.example.annotation.AopTest)")
@AopTest
public class WeatherForm implements Serializable {
  //...省略
}

下記のようにメソッドの引数にアノテーションを指定する方法では適用できません(有効になりません)。

NG
public void forecast(@AopTest WeatherForm form) {
  //...省略
}

バインディング

アノテーションをアドバイザにバインドすることができます。

OK
@Around("execution(* com.example.*..*.*(..)) && @args(aopTest)")
public Object a4(ProceedingJoinPoint pjp, AopTest aopTest) throws Throwable {
  //...省略
}

bean

Springコンテナが管理するbeanの名前で指定します。名前にワイルドカードを使用することができます。
この例では"ServiceImpl"という名前で終わるbeanのメソッドに適用しています。

@Around("bean(*ServiceImpl)")

@​annotation

'@annotation' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

指定するアノテーションを付与したメソッドに適用します。

OK
@Around("@annotation(com.example.annotation.AopTest)")
@AopTest
public void beforeTransaction() {
  //...省略
}

バインディング

アノテーションをアドバイザにバインドすることができます。

OK
@Around("@annotation(aopTest)")
public Object a2(ProceedingJoinPoint pjp, AopTest aopTest) throws Throwable {
  //...省略
}

サポートしていないポイントカット指定子

2017年9月時点

  • call
  • get
  • set
  • preinitialization
  • staticinitialization
  • initialization
  • handler
  • adviceexecution
  • withincode
  • cflow
  • cflowbelow
  • @this
  • @withincode

The full AspectJ pointcut language supports additional pointcut designators that are not supported in Spring. These are: call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, and @withincode. Use of these pointcut designators in pointcut expressions interpreted by Spring AOP will result in an IllegalArgumentException being thrown.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
61
Help us understand the problem. What are the problem?