Help us understand the problem. What is going on with this article?

より細かいポイントカットを行うためのポイントカット一覧

More than 3 years have passed since last update.

はじめに

時代が来るかも?アスペクト指向プログラミング, AspectJ言語とは何かをまとめていて、ポイントカットについて記述していたのだが、思いのほかポイントカットが多かった
長くて返って理解しづらくなったり、AspectJで実装されたポイントカットなどもあるみたいなのでわけることにした
独断と偏見でわけたのでご了承ください

まとめられなかったポイントカット

静的イニシャライザ関連のポイントカット

静的イニシャライザに関連するポイントカットにはstaticinitializationが用意されている
引数にタイプパターンを取り、クラスのstaticフィールドを初期化する静的イニシャライザが呼ばれて実行される「とき」を表す

Sample.java
// クラス名を直接書くか、ワイルドカードを使って書く
staticinitialization(Session+)

静的イニシャライザとは?

静的イニシャライザ(static initializer)、クラス・イニシャライザともいう
staticフィールドの値を初期化するために、各クラスごとに宣言される特別なメソッド

staticInitializer.java
static {
  // staticフィールドの値を初期化するコード
}

ジョインポイントの発生場所に関連するポイントカット

ポイントカットは演算子を使って組み合わせることができる
だが、注意が必要で上記の図のようにexecutionをcallが包んでいるように見えるのでcall && exectuionや
下のコードのように包んでいるように見えても、実際は違う

Sample.java
class Sample {
  Sample() {
    Main.init()
  }
}

class Main {
  static void init() {
    hoge();
  }
  static int length() {
    return hoge
  }
}

下の図のようにexecutionは水色の部分(ジョインポイントの外の部分)を指定していて、callは緑色の部分をしている状態なので
&& の条件がTrueになることはない

qiita8.PNG

だが、このような条件を作りたい場合どうすればよいか
その解決策に特定の種類のジョインポイントを選択するもののほかに、プログラム中の場所を条件にジョインポイントを選択するプリミティブ・ポイントカットも提供している

:black_small_square:within(タイプパターン)
タイプパターンに合致するクラスやインタフェースの宣言の中で発生するジョインポイントをすべて選択する
ジョインポイントの種類は問わない

:black_small_square:withincode(メソッドパターン)またはwithincode(コンストラクタパターン)
引数のパターンに合致するメソッドやコンストラクタの本体の中で発生するジョインポイントをすべて選択する
ジョインポイントの種類は問わない

上記を使うことにより、特定のクラスやメソッド内という指定の仕方ができるようになる

qiita9.PNG

業務フロー関連のポイントカット

業務フローに関連するポイントカットにはcflowcflowbelowの2つがある
引数にポイントカットを取り、「とき」を表す

Sample.java
cflow(call(void Main.init()))

:black_small_square:cflow
引数のポイントカットが選択するジョインポイントPの開始から終了までの間に発生するすべてのジョインポイントを選択する
cflowは、引数のポイントカットによって選択されたジョインポイントPを選択する

:black_small_square:cflowbelow
cflowとほぼ同じだが、cflowと異なり、引数のポイントカットによって選択されたジョインポイントPは選択しない

withincodeとcflowの違い

withincode

withincode.java
call(void Main.hogeB()) && withincode(void Main.init())

withincodeは引数のパターンに合致するメソッドの本体の中で発生するジョインポイントなので
この場合はmain.hogeAというメソッドが呼ばれるジョインポイントだけ
よってcall(void Main.hogeB())と一致するものが存在しない

cflow

cflow.java
call(void Main.hogeB()) && cflow(call(void Main.init()))

cflowは引数のポイントカットが選択するジョインポイントPの開始から終了までの間に発生するすべてのジョインポイントを選択するので
この場合はmain.hogeAとmain.hogeBというメソッドが呼ばれるジョインポイント
よってcall(void Main.hogeB())と一致するものが存在する

qiita10.PNG

アドバイス関連のポイントカット

callポイントカットは、メソッドパターンで指定されたメソッドが呼び出される「とき」をジョインポイントとして選択する
このジョインポイントはメソッドだけではなく、アスペクトの定義の中にあらわれるメソッド呼び出しも対象となる
これはcall以外のポイントカットにも言えることである

無限の再起呼び出し問題

Hello.java
impoort java.io.*;
aspect Tracer {
  pointcut tracedMethods(): call(* PrintStream.println(..));

  before(): tracedMethods() {
    System.out.println("** method call");
  }
}

public class Hello {
  public static void say() {
    System.out.println("Hello");
  }
  public static void main(String[] args) {
    say();
  }
}

上記のようなプログラムを書くと無限ループになってしまう

qiita11.PNG

この問題を避けるためにアドバイス関連のポイントカットにadviceexecutionがある
引数を取らず、任意のアドバイスの本体が実行されている「とき」を表す

Sample.java
!cflow(adviceexecution())
// アドバイスの本体を実行している間以外のすべてのジョインポイントを選択する

文脈情報を取り出すポイントカット

プログラムの実行文脈(context)の情報に関連するポイントカットにはthistargetargsの3つがある

:black_small_square:this
ポイントカットの引数に一致する型(サブクラスやサブインタフェースも含む)のインスタンスが実行している、メソッドやコンストラクタの本体の中で発生したジョインポイントをすべて選択する
ジョインポイントの種類は問わない

:black_small_square:target
ポイントカットの引数に一致する型(サブクラスやサブインタフェースも含む)のインスタンスを対象とするメソッド呼び出しやフィールド・アクセスを、ジョインポイントとしてすべて選択する
ジョインポイントの種類は問わない

:black_small_square:args
ポイントカットの引数に一致する型の引数をとるメソッドやコンストラクタ呼び出しなどを、ジョインポイントとして選択する

thisポイントカットの使い方

this変数が指すオブジェクトのクラスとポイントカットの引数と一致するときジョインポイントを選択する

Sample.java
call(* *(..)) && this(Session)
// 上記はSessionクラス、またはそのサブクラスのメソッドの中から任意のメソッドの呼び出しをジョインポイントとして選択する

targetポイントカットの使い方

メソッド呼び出しやフィールド・アクセスの対象となっているオブジェクトのクラスの型とポイントカットの引数と一致するときジョインポイントを選択する

Sample.java
class Session {}
class BookSession extends Session{} 
Sample.java
call(* Session.*(..)) && target(BookSession)
// 上記はSessionクラスで宣言されているメソッドを呼び出しているときのうち、BookSessionオブジェクトに対して呼び出しているときだけをジョインポイントとして選択する

Session s = new BookSession(301);
s.doIt();

argsポイントカットの使い方

Sample.java
call(* *(..)) && args(BookSession, ..)
// 第一引数がBookSessionクラスのインスタンスであるようなメソッド呼び出しをジョインポイントとして選択する

argsポイントカットも、型を調べるとき、引数のオブジェクトの実際の型を使うことに注意

Boolean式を使ったポイントカット

名前付きポイントカット

参考

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした