AspectJ 環境を構築しよう

Last Updated : 2004/4/3
asato <asato@ncfreak.com>

[ TOP ]

Pointcut Designators (Pointcuts)

(1.1rc1 OK)

pointcut designators の役割は、join point を選び出すことです。AspectJ では pointcut designators によって選び出すことのできる、さまざまな join point が定義されています。どのような join point が定義されているのかについての一覧は、詳しくは以下を参照してください:

この章では、AspectJ で使用できる各 pointcut designator にそれぞれについて、各 pointcut designator の動作や働きが分るようないくつかのシンプルなサンプルコードを紹介しています。コードの数は、それなりに多いですが、残念ながら 完全ではありません。つまり、各 pointcut designator について、できることできないこと、のすべてのパターンをカバーできているわけではありません。したがって、ここで紹介されているコード だけ を頼りにすると、後になって「こんな書き方もできたのか!」と驚くことになってしまうかもしれません。そのため、そのような驚きに遭遇しないようにするためにも「The AspectJ Programming Guide」に目を通すことを 本当に強く 推奨します。あるいは、今のところまだこの章でカバーできてない項目を 参照 してもらうと、どのくらいカバーできてないかが分かります。

Pointcut Designators (Pointcuts)

(1.1rc1 OK)

以下のようなプリミティブな pointcut が定義されています。

クラス・メソッド・コンストラクタ関連 例外関連
call(Signature) handler(TypePattern)
execution(Signature) フィールド関連
initialization(Signature) get(Signature)
preinitialization(Signature) set(Signature)
Static Initializers advice 関連
staticinitialization(TypePattern) adviceexecution()
オブジェクト関連 Lexical Extents
this(TypePattern) within(TypePattern)
target(TypePattern) withincode(Signature)
args(TypePattern, ...)
Control Flow Combination
cflow(Pointcut) ! Pointcut
cflowbelow(Pointcut) Pointcut0 && Pointcut1
Conditional Pointcut0 || Pointcut1
if(Expression) ( Pointcut )

call(Signature)

Signature にマッチするメソッドやコンストラクタの呼び出しが対象になります。コンストラクタを指定するには Class.new() という書き方をします (たとえば call( Hello.new() ) など)。

組み合わせる pointcut advice 利用度 コメント
call のみ before メソッドやコンストラクタの呼び出し に何らかの処理を行うコードを書くことができます。
after メソッドやコンストラクタの呼び出し に何らかの処理を行うコードを書くことができます。
around メソッドやコンストラクタの呼び出しの 前後 に何らかの処理を行うコードを書くことができます。さらには、オリジナルのメソッドやコンストラクタの呼び出しとは全く別のコードで置き換えることも可能です (メソッドが戻り値を伴っている場合は、同じ戻り値の型でリターンする必要があります)。

以下の節では、call pointcut を使った、次のような例を紹介します:

call(Signature) - その 1: メソッドに対して - その 1: call + before advice

(1.1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before() : call( void Main.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
method

call(Signature) - その 2: メソッドに対して - その 2: call + after advice

(1.1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	after() : call( void Main.method() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
method
after

call(Signature) - その 3: メソッドに対して - その 3: call + after advice + 例外

(1.1 OK)

public class Main {

	public static void main(String[] args) {

		try {
			new Main().method();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method() {
		throw new RuntimeException();
	}
}
public aspect MainAspect {

	after() : call( void Main.method() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
after
java.lang.RuntimeException

call(Signature) - その 4: メソッドに対して - その 4: call + after returning advice + 例外

(1.1 OK)

例外をスローするメソッドに対して、after returning advice を使用した場合についての例です。

public class Main {

	public static void main(String[] args) {

		try {
			new Main().method();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method() {
		throw new RuntimeException();
	}
}
public aspect MainAspect {

	after() returning : call( void Main.method() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
java.lang.RuntimeException
例 2:
public class Main {

	public static void main(String[] args) {

		try {
			new Main().method(true);
			new Main().method(false);

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method(boolean bool) {

		if (bool) {
			System.out.println("method");
	
		} else {
			throw new RuntimeException();
		}
	}
}
public aspect MainAspect {

	after() returning : call( void Main.method(boolean) ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
method
after
java.lang.RuntimeException

call(Signature) - その 5: メソッドに対して - その 5: call + after returning advice + 戻り値へのアクセス

(1.1 OK)

もし、あるメソッドが特定の戻り値を返すのであれば、after returning advice を使うことにより、advice 内でその戻り値にアクセスすることができます:

public class Main {

	public static void main(String[] args) {

		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "xxx";
	}
}
public aspect MainAspect {

	after() returning(String str) : call( String Main.getString() ) {
		System.out.println("after - " + str);
	}
}
java> java -cp dest aoptest.Main
after - xxx
xxx
例 2 : returning に書かれる型名が、必ずしも正確にメソッドの戻り値の型名と一致する必要がないことに注意してください。
public interface MyClass { }
public class MySubClass implements MyClass { }
public class Main {

	public static void main(String[] args) {

		System.out.println( new Main().createMySubClass() );
	}

	public MySubClass createMySubClass() {
		return new MySubClass();
	}
}
public aspect MainAspect {

	after() returning(MyClass my): call( MySubClass Main.createMySubClass() ) {
		System.out.println("after - " + my);
	}
}
java> java -cp dest aoptest.Main
after - aoptest.MySubClass@e53108
aoptest.MySubClass@e53108
例 3: 例 2 で述べたように、returning の型名と戻り値の型名の不一致に注意してください:
public class Main {

	public static void main(String[] args) {

		System.out.println( new Main().createMyClass() );
	}

	public MyClass createMyClass() {
		return new MySubClass();
	}
}
public aspect MainAspect {

	after() returning(MySubClass my): call( MyClass Main.createMyClass() ) {
		System.out.println("after - " + my);
	}
}
java> java -cp dest aoptest.Main
after - aoptest.MySubClass@e53108
aoptest.MySubClass@e53108
例 4 : 例 3 のより分かりやすい例かもしれません:
public class Main {

	public static void main(String[] args) {

		System.out.println( new Main().createObject() );
	}

	public Object createObject() {
		return new String("xxx");
	}
}
public aspect MainAspect {

	after() returning(String str): call( Object Main.createObject() ) {
		System.out.println("after - " + str + " : length = " + str.length());
	}
}
java> java -cp dest aoptest.Main
after - xxx : length = 3
xxx

call(Signature) - その 6: メソッドに対して - その 6: call + after throwing advice + 例外

(1.1 OK)

例外をスローするメソッドに対して、call pointcut と after throwing advice を組み合わせて使用する場合の例です。

public class Main {

	public static void main(String[] args) {

		try {
			new Main().method();
		
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method() {
		throw new RuntimeException();
	}
}
public aspect MainAspect {

	after() throwing : call( void Main.method() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
after
java.lang.RuntimeException
例 2:
public class Main {

	public static void main(String[] args) {

		try {
			new Main().method(true);
			new Main().method(false);
		
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method(boolean bool) {

		if (bool) {
			System.out.println("method");

		} else {
			throw new RuntimeException();
		}
	}
}
public aspect MainAspect {

	after() throwing : call( void Main.method(boolean) ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
method
after
java.lang.RuntimeException

call(Signature) - その 7: メソッドに対して - その 7: call + after throwing advice + 例外 + 例外オブジェクトへのアクセス

(1.1 OK)

after throwing advice では、スローされた例外オブジェクトにアクセスできるようなコードも書くことができます。

public class Main {

	public static void main(String[] args) {

		try {
			new Main().method();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void method() {
		throw new RuntimeException();
	}
}
public aspect MainAspect {

	after() throwing(RuntimeException e) : call( void Main.method() ) {
		System.out.println("after - " + e);
	}
}
java> java -cp dest aoptest.Main
after - java.lang.RuntimeException
java.lang.RuntimeException
例 2: throwing に書く例外の型名は、かならずしも実際にスローされる例外クラスの型と一致している必要がないことに注意してください:
public aspect MainAspect {

	after() throwing(Exception e) : call( void Main.method() ) {
		System.out.println("after - " + e);
	}
}
java> java -cp dest aoptest.Main
after - java.lang.RuntimeException
java.lang.RuntimeException
例 3:
public class MyExceptionA extends Exception { }
public class MyExceptionB extends Exception { }
public class Main {

	public static void main(String[] args) {

		try {
			new Main().method(true); // MyExceptionA をスロー

		} catch (Exception e) {
			System.out.println(e);
		}

		try {
			new Main().method(false); // MyExceptionB をスロー

		} catch (Exception e) {
			System.out.println(e);
		}


	}

	public void method(boolean bool) throws Exception {

		if (bool) {
			throw new MyExceptionA();

		} else {
			throw new MyExceptionB();
		}
	}
}
public aspect MainAspect {

	private pointcut method() : call( void Main.method(boolean) );


	after() throwing(MyExceptionA e) : method() {
		System.out.println("after - " + e);
	}

	after() throwing(MyExceptionB e) : method() {
		System.out.println("after - " + e);
	}
}
java> java -cp dest aoptest.Main
after - aoptest.MyExceptionA
aoptest.MyExceptionA
after - aoptest.MyExceptionB
aoptest.MyExceptionB

call(Signature) - その 8: コンストラクタに対して - その 1: call + before advice

(1.1 OK)

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before() : call( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()

call(Signature) - その 9: コンストラクタに対して - その 2: call + after advice

(1.1 OK)

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	after() : call( Main.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
Main()
after

call(Signature) - その 10: コンストラクタに対して - その 3: call + after returning advice

(1.1 OK)

この例では、after returning advice を使うことによって、新しく構築された (new された) オブジェクトに advice 内でアクセスする方法を紹介します。

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	after() returning(Main main) : call( Main.new() ) {
		System.out.println("after - " + main);
	}
}
java> java -cp dest aoptest.Main
Main()
after - aoptest.Main@1888759
ここで、単に (after returning ではなく) after advice を用いるだけでは、上記の例のように main オブジェクトにアクセスできるコードを 書けない ことに注意してください。例えば、以下のように、call pointcut と target pointcut を組み合わせることにより、新しく構築された main オブジェクトを参照しようとする試みは失敗します:
public aspect MainAspect {

	after(Main main) : target(main) && call( Main.new() ) {
		System.out.println("after - " + main);
	}
}
java> java -cp dest aoptest.Main
Main()
同様に、target pointcut を 使用せずに、thisJoinPoint を用いて、間接的に target オブジェクトを得ようとする方法も、うまくいきません:
public aspect MainAspect {

	after() : call( Main.new() ) {
		System.out.println("after - " + thisJoinPoint.getTarget() );
	}
}
java> java -cp dest aoptest.Main
Main()
after - null

call(Signature) - その 11: 既存ライブラリに対しては?

(1.1 OK)

今までの例では、独自に作ったクラスに対しての call pointcut の使用例を紹介していました。一方、この例では既存のライブラリ (Java の API) に対してはどうなのか? という例を紹介します。ここでは Integer クラスのコンストラクタの呼び出しを対象にしています:

public class Main {

	public static void main(String[] args) {

		Integer i = new Integer(10);

		System.out.println(i);
	}
}
public aspect MainAspect {

	before() : call( Integer.new(int) ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
10

call(Signature) - その 12: args pointcut との組み合わせ

(1.1 OK)

この例では call pointcut と args pointcut を組み合わせた場合の例を紹介します。

public class Main {

	public static void main(String[] args) {
		new Main().printString("aaa");
	}

	public void printString(String str) {
		System.out.println(str);
	}
}
public aspect MainAspect {

	before() : args(String) && call( void Main.printString(String) ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
aaa
例 2:
public class Main {

	public static void main(String[] args) {

		new Main().printString("aaa");

		new Main().printInt(10);
	}

	public void printString(String str) {
		System.out.println(str);
	}

	public void printInt(int i) {
		System.out.println(i);
	}
}
public aspect MainAspect {

	pointcut printCall() :
		call( void Main.printString(String) ) || call( void Main.printInt(int) );

	before() : args(String) && printCall() {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
aaa
10
例 3:
public class Main { // 上と変更なし

	public static void main(String[] args) {
		new Main().printString("aaa");
		new Main().printInt(10);
	}

	public void printString(String str) {
		System.out.println(str);
	}
	public void printInt(int i) {
		System.out.println(i);
	}
}
public aspect MainAspect {

	pointcut printCall() : call( void Main.print*(..) );

	before() : args(String) && printCall() {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
aaa
10

call(Signature) - その 13: target pointcut との組み合わせ

(1.1 OK)

この例では call pointcut と target pointcut を組み合わせた例を紹介します:

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before() : target(Main) && call( void Main.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
method
例 2:
public class YourMain {

	public void method() {
		System.out.println("YourMain - method");
	}
}
public class Main {

	public static void main(String[] args) {

		new Main().method();

		new YourMain().method();
	}

	public void method() {
		System.out.println("Main - method");
	}
}
public aspect MainAspect {

	pointcut methodCall() :
		call( void Main.method() ) || call( void YourMain.method() );

	before() : target(Main) && methodCall() {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main - method
YourMain - method

call(Signature) - その 14 : コンストラクタに対する call + around

(1.1 OK)

public class Main {

	public static void main(String[] args) {

		System.out.println( new Main() );
	}
}
public aspect MainAspect {

	Main around() : call( Main.new() ) {
		return new MyMain();
	}

	private static class MyMain extends Main { }
}
java> java -cp dest aoptest.Main
aoptest.MainAspect$MyMain@6e1408
例 2:
public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	Main around() : call( Main.new() ) {
		return new MyMain();
	}

	private static class MyMain extends Main {
		public void method() {
			System.out.println("my method");
		}
	}
}
java> java -cp dest aoptest.Main
my method
例 3: もちろん、既存のクラスに対しても同様のことができます:
public class Main {

	public static void main(String[] args) {

		System.out.println( new ArrayList().getClass() );
	}
}
public aspect MainAspect {

	ArrayList around() : call( ArrayList.new() ) {
		return new MyArrayList();
	}

	private static class MyArrayList extends ArrayList { }
}
java> java -cp dest aoptest.Main
class aoptest.MainAspect$MyArrayList
例 4: around advice の特性と ArrayList クラスが List interface を実装しているということにより、以下のように書けると思われるかもしれませんが、コンパイルエラーとなります:
public class Main { // 上と変更なし

	public static void main(String[] args) {

		System.out.println( new ArrayList().getClass() );
	}
}
public aspect MainAspect {

	List around() : call( ArrayList.new() ) {
		return proceed(); // そのままのオリジナルの呼び出し
	}
}
例 5: また、以下のように書くこともできません:
public class Main { // 上と変更なし

	public static void main(String[] args) {

		System.out.println( new ArrayList().getClass() );
	}
}
public aspect MainAspect {

	List around() : call( ArrayList.new() ) {
		return new LinkedList();
	}
}
例 6: さらに以下のように書けばコンパイル 通りますが ClassCastException がスローされます:
public class Main { // 上と変更なし

	public static void main(String[] args) {

		System.out.println( new ArrayList().getClass() );
	}
}
public aspect MainAspect {

	Object around() : call( ArrayList.new() ) {
		return new LinkedList();
	}
}
java> java -cp dest aoptest.Main
Exception in thread "main" java.lang.ClassCastException
        at aoptest.Main.main(Main.java:8)
例 7: あるいは、以下のように書いてもコンパイルエラーですが:
public aspect MainAspect {

	List around() : call( List+.new() ) {
		return proceed(); // そのままのオリジナルの呼び出し
	}
}
例 8: 以下のように、around の戻り値を Object に変更すれば、コンパイルも通り、実行もうまくいきます:
public aspect MainAspect {

	Object around() : call( List+.new() ) {
		return proceed(); // そのままのオリジナルの呼び出し
	}
}
例 9: ただし、以下のようにするのは、コンパイルは通りますが、実行時に ClassCastException がスローされます:
public aspect MainAspect {

	Object around() : call( List+.new() ) && !within(MainAspect) {
		return new LinkedList();
	}
}
例 10: コンストラクタに対する around の戻り値として null を返すこともできます:
public class Main {

	public static void main(String[] args) {

		System.out.println( new Main() );
	}
}
public aspect MainAspect {

	Main around() : call( Main.new() ) {
		return null;
	}
}
java> java -cp dest aoptest.Main
null

call(Signature) - その 15 : コンストラクタに対する call + around + proceed()

(1.1 OK)

public class Main {

	public static void main(String[] args) {

		System.out.println( new Main() );
	}
}
public aspect MainAspect {

	Main around() : call( Main.new() ) {

		Main main = proceed();

		System.out.println("around - " + main);
		
		return main;
	}
}
java> java -cp dest aoptest.Main
around - aj.Main@1888759
aj.Main@1888759
例 2: proceed() は advice 内で何度でも呼び出せます:
public aspect MainAspect {

	Main around() : call( Main.new() ) {

		Main main1 = proceed();
		Main main2 = proceed();

		System.out.println("around - main1: " + main1);
		System.out.println("around - main2: " + main2);

		return main1;
	}
}
java> java -cp dest aoptest.Main
around - main1: aj.Main@1888759
around - main2: aj.Main@6e1408
aj.Main@1888759
例 3: proceed() によって得られるオブジェクトの型は、around advice の戻り値の型になることに注意してください:
public class Main {

	public static void main(String[] args) {
		System.out.println( new Main() );
	}
}
public aspect MainAspect {

	Object around() : call( Main.new() ) {

		Main main = proceed(); // コンパイルエラー。Object main にしなければならない。

		return main;
	}
}

call(Signature) - その 16 : メソッドに対する call + around

(1.1 OK)

public class Main {

	public static void main(String[] args) {

		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around() : call( String Main.getString() ) {
		return "xxx";
	}
}
java> java -cp dest aoptest.Main
xxx
例 2: proceed() を呼び出すことにより、オリジナルのメソッドを呼び出すことができます:
public class Main { // 上と変更なし

	public static void main(String[] args) {

		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around() : call( String Main.getString() ) {
		return "*** " + proceed();
	}
}
java> java -cp dest aoptest.Main
*** aaa

call(Signature) - その 17 : ポリモーフィズムを伴う場合 (スーパークラスのメソッドに対して)

(1.1 OK)

public class Hello {

	public void hello() {
		System.out.println("hello");
	}
}
public class MyHello extends Hello {

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main {

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect HelloAspect {

	before() : call( void Hello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
hello

before
my hello

before
my hello
例 2: この例からは、call pointcut を用いては、細かな join point の制御ができないことが分かります。例えば、プログラマの目的が、実際に Hello クラスのインスタンスのあるメソッドが呼ばれた場合に advice を実行することだとすると、うまくいきません (サブクラスのインスタンスに対してのメソッドの呼び出しも join point として含んでしまいます)。

そのような要求に対しての 1 つの解は (他にもやり方があるかもしれません)、call pointcut と target pointcut を組み合わせることです:

public class Main { // 前と変更なし

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect MainAspect {

	before() : call( void Hello.hello() ) && target(Hello) && !target(MyHello) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
hello

my hello

my hello
例 3: その他のより細かい join point の指定が必要とされる要求として考えられるものには、どのクラスのインスタンスかに関わらず、特定の型として呼ばれた場合を join point とする、というものがあります:
public class Main { // 前と変更なし

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect MainAspect {

	before() : call( void Hello.hello() ) && !call( void MyHello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
hello

before
my hello

my hello

call(Signature) - その 18 : ポリモーフィズムを伴う場合 (サブクラスのメソッドに対して)

(1.1 OK)

public class Hello {

	public void hello() {
		System.out.println("hello");
	}
}
public class MyHello extends Hello {

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main {

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect HelloAspect {

	before() : call( void MyHello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
hello

my hello

before
my hello

call(Signature) - その 19 : ポリモーフィズムを伴う場合 - 存在しないメソッド

(1.1 OK)

この例は、例 17 に関連しています。

public class Hello { } // void hello() メソッドが定義されてないことに注意。
public class MyHello extends Hello {

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main {

	public static void main(String[] args) {

		MyHello hello = new MyHello();
		hello.hello();
	}
}
public aspect MainAspect {

	before() : call( void Hello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
my hello
advice が実行されて いない ことに注意してください。この結果は、例 17 のものとは異なります。つまり、もし、Hello クラスに void hello() メソッドを定義し:
public class Hello {

	public void hello() {
		System.out.println("hello");
	}
}
Main を実行したとすると、実行結果は:
java> java -cp dest aoptest.Main
before
my hello
となり、advice が実行されています。

例 2: Hello クラスに void hello() メソッドを定義すること なく、Hello クラスを継承するあるクラスが、もし void hello() メソッドを定義していたならば、特定の advice を実行する、ということが要求である場合、どうすればいいのでしょうか? タイプパターン (Type Patterns) を使用します:

public class Hello { }
public class MyHello extends Hello { // 前と変更なし

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main { // 前と変更なし

	public static void main(String[] args) {

		MyHello hello = new MyHello();
		hello.hello();
	}
}
public aspect MainAspect {

	before() : call( void Hello+.hello() ) { // "+" に注意
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
my hello

call(Signature) - その 20 : call join point での thisJoinPoint - その 1

(1.1 OK)

この例とこの次のいくつかの例では、call pointcut を使ったときに、thisJoinPoint からどんな情報を取得できるかを紹介します。

public class Hello {

	public void hello() { }
}
public class Main {

	public static void main(String[] args) {
		new Hello().hello();
	}
}
public aspect MainAspect {

	before() : call( void Hello.hello() ) {
		System.out.println("this  : " + thisJoinPoint.getThis() );
		System.out.println("target: " + thisJoinPoint.getTarget() );
	}
}
java> java -cp dest aoptest.Main
this  : null
target: aoptest.Hello@15b7986
例 2: 以下は、thisJoinPoint.getTarget() で取得しているオブジェクトが実際に、main メソッド内で呼ばれたオブジェクトと同じかどうかを確認するコードです (Main クラスだけを変更しています):
public class Main {

	public static void main(String[] args) {

		Hello hello = new Hello();
		hello.hello();

		System.out.println("hello == " + hello);
	}
}
実行結果は:
java> java -cp dest aoptest.Main
this  : null
target: aoptest.Hello@15b7986
hello == aoptest.Hello@15b7986
となり、同じオブジェクトであることが分かります。

call(Signature) - その 21 : call join point での thisJoinPoint - その 2

(1.1 OK)

この例は、どこで Hello オブジェクトの void hello() メソッドを呼び出しているのかの違いを除けば、前の例と同じです。

public class Hello {

	public void hello() { }
}
public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {
		new Hello().hello();
	}
}
public aspect HelloAspect {

	before() : call( void Hello.hello() ) {
		System.out.println("this  : " + thisJoinPoint.getThis() );
		System.out.println("target: " + thisJoinPoint.getTarget() );
	}
}
java> java -cp dest aoptest.Main
this  : aoptest.Main@12b6651
target: aoptest.Hello@4a5ab2
例 2: 以下は、thisJoinPoint.getThis() と thisJoinPoint.getTarget() のそれぞれで取得できるオブジェクトが、実際に、void hello() メソッドの呼び出し側と呼ばれる側と同じであるかどうかを確認できるコードです:
public class Main {

	public static void main(String[] args) {

		Main main = new Main();
		main.method();

		System.out.println("main == " + main);
	}

	public void method() {
		Hello hello = new Hello();
		hello.hello();

		System.out.println("hello == " + hello);
	}
}
実行結果は:
java> java -cp dest aoptest.Main
this  : aoptest.Main@15b7986
target: aoptest.Hello@87816d
hello == aoptest.Hello@87816d
main == aoptest.Main@15b7986
となり、同じことが確認できます。

call(Signature) - その 22 : call と this pointcut

(1.1 OK)

ここでは、call pointcut と this pointcut を組み合わせた場合の使用例を紹介します。call pointcut と this pointcut を組み合わせることにより、例えば、あるメソッドの呼び出し側についての制約(どのクラスのオブジェクトがメソッドを呼んだときを join point として選び出したいのか)を課すことや、あるいは、呼び出し側のオブジェクトを advice 内で使用したりできるようになります。

public class Hello { // 呼ばれる側
	public void hello() { }
}
public class Main {

	public static void main(String[] args) {

		Main main = new Main(); // 呼び出し側
		main.method();
	}

	public void method() {
		Hello hello = new Hello();
		hello.hello();
	}
}
public aspect MainAspect {

	before() : this(Main) && call( void Hello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
例 2: 前の例では、this pointcut を使うことの意味はそれほど感じませんでした。というのも、これだけのコードの場合には、実際には、this pointcut がなくてもプログラムの実行結果は同じになるためです。

この例では、期待通りの動作を this pointcut が行ってくれるかどうかを確認するために、前の例を少し変更します。前の例では、Main オブジェクトの void method() メソッド内から void hello() メソッドを呼んでいましたが、この例では、void main(String[]) メソッドから直接 void hello() メソッドを呼び出します。

public class Hello { // 前と変更なし
	public void hello() { }
}
public class Main {

	public static void main(String[] args) {

		new Hello().hello();
	}
}
public aspect MainAspect {

	before() : this(Main) && call( void Hello.hello() ) {
		System.out.println("before");
	}
}
プログラムの実行結果は、期待通りに、呼び出し側のオブジェクトは存在しないので、何も表示されません:
java> java -cp dest aoptest.Main
// advice は実行されない
例 3: この例では、さらに動作の確認のために、お互いに関係のないオブジェクトのそれぞれから、あるクラス(Hello) のメソッド (void hello()) を呼び出したときを考えます。ここでは、呼び出し側のオブジェクトとして ProgramA クラスと ProgramB クラスのオブジェクトを考えます。ProgramA と ProgramB のそれぞれのコンストラクタで、Hello オブジェクトを生成し、void hello() メソッドを呼び出しています。MainAspect アスペクトでは、ProgramA のオブジェクトが void hello() メソッドを呼んだときだけ advice が実行されるような pointcut を書いています。
public class Hello {
	public void hello() {
		System.out.println("hello");
	}
}
public class ProgramA {
	public ProgramA() {
		new Hello().hello();
	}
}
public class ProgramB {
	public ProgramB() {
		new Hello().hello();
	}
}
public class Main {

	public static void main(String[] args) {
	
		System.out.println("ProgramA:");
		new ProgramA();

		System.out.println("ProgramB:");
		new ProgramB();
	}
}
public aspect HelloAspect {

	pointcut hello() : this(ProgramA) && call( void Hello.hello() );

	before() : hello() {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
ProgramA:
before
hello

ProgramB:
hello
例4: この例では、呼び出し側のオブジェクトに advice 内でアクセスする書き方を紹介します。
public class Hello {
	public void hello() {
		System.out.println("hello");
	}
}
public class Main {

	public static void main(String[] args) {

		Main main = new Main();
		main.method();

		System.out.println("main - " + main);
	}
	
	public void method() {
		new Hello().hello();
	}
}
public aspect MainAspect {

	before(Main main) : this(main) && call( void Hello.hello() ) {
		System.out.println("before - " + main);
	}
}
java> java -cp dest aoptest.Main
before - aoptest.Main@6e1408
hello
main - aoptest.Main@6e1408

execution(Signature)

execution pointcut (execution join point) は call pointcut (call join point)とほとんど同じに見えますが異なります。この二つの違いについては AspectJ の FAQ をご覧下さい:

以下では次のような項目についてのサンプルコードを紹介します:

execution(Signature) - その 1 : メソッドに対して

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before() : execution( void Main.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
method

execution(Signature) - その 2 : 既存のライブラリに対して

(1.1rc1 OK)

この例では既存のライブラリ (Java の標準 API など) にたいしての execution pointcut の例を紹介します。

以下のように Interger クラスのコンストラクタに対しての execution pointcut を考えます。

public class Main {

	public static void main(String[] args) {
		new Integer(10);
	}
}
public aspect MainAspect {

	before() : execution( Integer.new(int) ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
// 出力なし

execution(Signature) - その 3 : execution での thisJoinPoint

(1.1rc1 OK)

call pointcut と execution pointcut の違いが現れる 1 つのポイントは、どこが joinpoint として扱われてるか、です。call pointcut は、外側からのもので、execution pointcut は内側からのものです。

大雑把に表すと以下のような感じです:

public class Main {
	public void method() {
		Caller caller = new Caller();
		caller.method();
	}
}
public class Caller {
	public void method() {
		Callee callee = new Callee();
		callee.method() // <-- ここでのポイント (a) か
	}
}

public class Callee {
	public void method() { // <-- それともここでのポイント (b) か
		
	}
}
(a) では target としては callee オブジェクトが対象となり this としては caller オブジェクトが対象となります。

一方 (b) では、target としては callee オブジェクトが、また this としても callee オブジェクトが対象となります。

したがって、もし join point として (a) を選び出したいなら call(void Callee.method() ) を、もし (b) を選び出したいなら execution( void Callee.method() ) と書くことができます。

この違いは、より特定の join point を選び出すために、call pointcut や execution pointcut をその他の pointcut (特に this pointcut や target pointcut) と組み合わせる時に重要になります。

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before() : execution( void Main.method() ) {
		System.out.println("this  : " + thisJoinPoint.getThis() );
		System.out.println("target: " + thisJoinPoint.getTarget() );
	}
}
java> java -cp dest aoptest.Main
this  : aj.Main@1bc4459
target: aj.Main@1bc4459

execution(Signature) - その 4 : コンストラクタに対する execution + around - その 1

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	void around() : execution( Main.new() ) {
		System.out.println("around");
	}
}
java> java -cp dest aoptest.Main
around

execution(Signature) - その 5 : コンストラクタに対する execution + around - その 2: 既存のライブラリに対して

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Integer(10);
	}
}
public aspect MainAspect {

	void around() : execution( Integer.new(int) ) {
		System.out.println("around");
	}
}
java> java -cp dest aoptest.Hello
// 出力なし

execution(Signature) - その 6 : メソッドに対する execution + around - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around() : execution( String Main.getString() ) {
		return "xxx";
	}
}
java> java -cp dest aoptest.Main
xxx

execution(Signature) - その 7 : メソッドに対する execution + around - その 2 : 既存のライブラリに対して

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		System.out.println( new Integer(10).intValue() );
	}
}
public aspect MainAspect {

	int around() : execution( int Integer.intValue() ) {
		return 0;
	}
}
java> java -cp dest aoptest.Main
10

execution(Signature) - その 8

(1.1rc1 OK)

public class Hello {

	public void hello() {
		System.out.println("hello");
	}
}
public class MyHello extends Hello {

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main {

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect MainAspect {

	before() : execution( void Hello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
hello

before
my hello

before
my hello

execution(Signature) - その 9

(1.1rc1 OK)

public class Hello {

	public void hello() {
		System.out.println("hello");
	}
}
public class MyHello extends Hello {

	public void hello() {
		System.out.println("my hello");
	}
}
public class Main {

	public static void main(String[] args) {

		Hello hello1 = new Hello();
		hello1.hello();

		System.out.println();

		Hello hello2 = new MyHello();
		hello2.hello();

		System.out.println();

		MyHello hello3 = new MyHello();
		hello3.hello();
	}
}
public aspect MainAspect {

	before() : execution( void MyHello.hello() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
hello

before
my hello

before
my hello
実行結果が call pointcut での実行結果と異なることに注意してください。MainAspect アスペクトでの execution を call に変更して実行すると、以下のような結果になります:
java> java -cp dest aoptest.Main
hello

my hello

before
my hello

handler(TypePattern)

handler pointcut は例外に関するものです。

handler(TypePattern) - その 1

(1.1rc1 OK)

この例では、例外をスローするメソッドとして Class.forName(String) を考えます。以下のコードから見られるように "xxx" という存在しないクラス名を指定することで、ClassNotFoundException 例外が必ずスローされるようにプログラムしてあります:

public class Main {

	public static void main(String[] args) {

		try {
			Class.forName("xxx"); // xxx は存在しないクラス

		} catch (ClassNotFoundException e) {
			System.out.println(e);
		}
	}
}
handler pointcut は以下のように書きます:
public aspect MainAspect {

	before(): handler(ClassNotFoundException) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
java.lang.ClassNotFoundException: xxx

handler(TypePattern) - その 2 : after advice との組み合わせ

(1.1rc1 OK)

この例では、前の例では before advice を使うことにより handler pointcut の動作を見てみました。では after advice ではどうでしょうか? 答えは、コンパイルはできるが、動作はサポートされてない、です:

public class Main {

	public static void main(String[] args) {

		try {
			Class.forName("xxx"); // 存在しないクラス

		} catch (ClassNotFoundException e) {
			System.out.println(e);
		}
	}
}
public aspect MainAspect {

	after(): handler(ClassNotFoundException) { // after advice との組み合わせは無理
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
java.lang.ClassNotFoundException: xxx

handler(TypePattern) - その 3 : around advice との組み合わせ

(1.1rc1 OK)

次は、handler pointcut と around advice との組み合わせの実験です。結果は after advice のときと同様に、コンパイルはできるが、動作はサポートされてない、です:

public class Main {

	public static void main(String[] args) {

		try {
			Class.forName("xxx"); // 存在しないクラス

		} catch (ClassNotFoundException e) {
			System.out.println(e);
		}
	}
}
public aspect MainAspect {
	void around(): handler(ClassNotFoundException) {
		System.out.println("around");
	}
}
java> java -cp dest aoptest.Main
java.lang.ClassNotFoundException: xxx

handler(TypePattern) - その 4 : 実行時例外は? - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = null;
		main.method(); // NullPointerException
	}
	
	public void method() {}
}
public aspect MainAspect {

	before(): handler(NullPointerException) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
Exception in thread "main" java.lang.NullPointerException
        at aoptest.Main.main(Main.java:10)

handler(TypePattern) - その 5 : 実行時例外は? - その 2

(1.1rc1 OK)

もし try - catch を使っていたら?

public class Main {

	public static void main(String[] args) {

		try {
			Main main = null;
			main.method();

		} catch (NullPointerException e) {
			System.out.println(e);
		}
	}

	public void method() {}
}
public aspect MainAspect {

	before(): handler(NullPointerException) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
java.lang.NullPointerException

handler(TypePattern) - その 6 : 例外オブジェクトへのアクセス

(1.1rc1 OK)

この例では handler pointcut と args pointcut を組み合わせることで、スローされた例外オブジェクトに advice 内でアクセスできることを紹介します:

public class Main {

	public static void main(String[] args) {

		try {
			Class.forName("xxx"); // 存在しないクラス

		} catch (ClassNotFoundException e) {
			System.out.println(e);
		}
	}
}
public aspect MainAspect {

	before(ClassNotFoundException e): args(e) && handler(ClassNotFoundException)
	{
		System.out.println("before - " + e);
	}
}
java> java -cp dest aoptest.Main
before - java.lang.ClassNotFoundException: xxx
java.lang.ClassNotFoundException: xxx

adviceexecution()

adviceexecution() - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}
}
public aspect MyMainAspect {

	before(): adviceexecution() && within(MainAspect) {
		System.out.println("adviceexecution");
	}
}
java> java -cp dest aoptest.Main
adviceexecution
before
method

adviceexecution() - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}

	after(): call( void Main.method() ) {
		System.out.println("after");
	}
}
public aspect MyMainAspect {

	before(): adviceexecution() && within(MainAspect) {
		System.out.println("adviceexecution");
	}
}
java> java -cp dest aoptest.Main
adviceexecution
before
method
adviceexecution
after

adviceexecution() - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}
}
public aspect MainAspect2 {

	after(): call( void Main.method() ) {
		System.out.println("after");
	}
}
public aspect MyMainAspect {

	before(): adviceexecution() && within(MainAspect) {
		System.out.println("adviceexecution");
	}
}
java> java -cp dest aoptest.Main
adviceexecution
before
method
after

adviceexecution() - その 4

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}
}
public aspect MainAspect2 {

	after(): call( void Main.method() ) {
		System.out.println("after");
	}
}
public aspect MyMainAspect {

	before(): adviceexecution() && !within(MyMainAspect) {
		System.out.println("adviceexecution");
	}
}
java> java -cp dest aoptest.Main
adviceexecution
before
method
adviceexecution
after

adviceexecution() - その 5 : adviceexecution + around advice その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}
}
public aspect MyMainAspect {

	void around(): adviceexecution() && !within(MyMainAspect) {
		System.out.println("adviceexecution");
	}
}
java> java -cp dest aoptest.Main
adviceexecution
method

adviceexecution() - その 6 : adviceexecution + around advice その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): call( void Main.method() ) {
		System.out.println("before");
	}
}
public aspect MyMainAspect {

	void around(): adviceexecution() && !within(MyMainAspect) {
		System.out.println("adviceexecution");
		proceed();
	}
}
java> java -cp dest aoptest.Main
adviceexecution
before
method

adviceexecution() - その 7 : adviceexecution + around advice その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around(): call( String Main.getString() ) {
		return proceed();
	}
}
public aspect MyMainAspect {

	Object around(): adviceexecution() && !within(MyMainAspect) {
		System.out.println("adviceexecution");
		return proceed();
	}
}
java> java -cp dest aoptest.Main
adviceexecution
aaa

adviceexecution() - その 8 : adviceexecution + around advice その 4

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		System.out.println( new Main().getString() );
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around(): call( String Main.getString() ) {
		return proceed();
	}
}
public aspect MyMainAspect {

	Object around(): adviceexecution() && !within(MyMainAspect) {
		return "xxx";
	}
}
java> java -cp dest aoptest.Main
xxx

adviceexecution() - その 9 : adviceexecution + args + around advice - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	before(Main main): target (main) && call( void Main.method() ) {
	}
}
public aspect MyMainAspect {

	before(Main main): args(main) && adviceexecution() && !within(MyMainAspect) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
aoptest.Main@1172e08

adviceexecution() - その 10 : adviceexecution + args + around advice - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	void around(Main main): target (main) && call( void Main.method() ) {
	}
}
public aspect MyMainAspect {

	before(Main main): args(main) && adviceexecution() && !within(MyMainAspect) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
// 出力なし
なぜ出力なし?
public aspect MyMainAspect {

	before(): adviceexecution() && !within(MyMainAspect) {
		System.out.println( Arrays.asList(thisJoinPoint.getArgs()) );

		AdviceSignature sig =
			(AdviceSignature)thisJoinPoint.getSignature();

		System.out.println( Arrays.asList( sig.getParameterTypes() ) );
	}
}
java> java -cp dest aoptest.Main
[aoptest.Main@e53108, null]
[class aoptest.Main, class org.aspectj.runtime.internal.AroundClosure]

adviceexecution() - その 11 : adviceexecution + args + around advice - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	void around(Main main): target (main) && call( void Main.method() ) {
	}
}
public aspect MyMainAspect {

	before(Main main): args(main, ..) && adviceexecution() && !within(MyMainAspect) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
aoptest.Main@1172e08

adviceexecution() - その 12 : adviceexecution + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before(): call( void Main.method() ) { }
}

import org.aspectj.lang.*;
import org.aspectj.lang.reflect.*;

public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	before(): adviceexecution() && !within(MyMainAspect) {

		println("getTarget() - " + thisJoinPoint.getTarget() );
		println("getThis()   - " + thisJoinPoint.getThis() );
		println("getArgs()   - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		println("");

		Class type = thisJoinPoint.getSignature().getDeclaringType();
		println("getSignature().getDeclaringType() - " +  type);


		Signature sig = thisJoinPoint.getSignature();
		println("getSignature().getClass()         - " + sig.getClass() );

		println("");

		AdviceSignature adviceSig = (AdviceSignature)thisJoinPoint.getSignature();
		println("getReturnType() - " + adviceSig.getReturnType() );
	}
}
java> java -cp dest aoptest.Main
getTarget() - aoptest.MainAspect@12b6651
getThis()   - aoptest.MainAspect@12b6651
getArgs()   - []

getSignature().getDeclaringType() - class aoptest.MainAspect
getSignature().getClass()         - class org.aspectj.runtime.reflect.AdviceSignatureImpl

getReturnType() - void

adviceexecution() - その 13 : adviceexecution + thisJoinPoint - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().getString();
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around (): call( String Main.getString() ) {
		return proceed();
	}
}
public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	before(): adviceexecution() && !within(MyMainAspect) {

		println("getArgs()           - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		AdviceSignature sig = (AdviceSignature)thisJoinPoint.getSignature();

		println("getReturnType()     - " + sig.getReturnType() );
		println("getParameterTypes() - " + Arrays.asList( sig.getParameterTypes() ) );

	}
}
java> java -cp dest aoptest.Main
getArgs()           - [null]
getReturnType()     - class java.lang.String
getParameterTypes() - [class org.aspectj.runtime.internal.AroundClosure]

adviceexecution() - その 14 : adviceexecution + thisJoinPoint - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().getString();
	}

	public String getString() {
		return "aaa";
	}
}
public aspect MainAspect {

	String around (): call( String Main.getString() ) {
		return proceed();
	}
}
public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	Object around(): adviceexecution() && !within(MyMainAspect) {

		println("getArgs()           - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		AdviceSignature sig = (AdviceSignature)thisJoinPoint.getSignature();

		println("getReturnType()     - " + sig.getReturnType() );
		println("getParameterTypes() - " + Arrays.asList( sig.getParameterTypes() ) );

		return proceed();
	}
}
java> java -cp dest aoptest.Main
getArgs()           - [aoptest.Main$AjcClosure1@19189e1]
getReturnType()     - class java.lang.String
getParameterTypes() - [class org.aspectj.runtime.internal.AroundClosure]

adviceexecution() - その 15 : adviceexecution + thisJoinPoint - その 4

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	before(Main main): target (main) && call( void Main.method() ) {
		System.out.println(main);
	}
}
public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	before(): adviceexecution() && !within(MyMainAspect) {

		println("getArgs()           - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		AdviceSignature sig = (AdviceSignature)thisJoinPoint.getSignature();

		println("getParameterTypes() - " + Arrays.asList( sig.getParameterTypes() ) );

	}
}
java> java -cp dest aoptest.Main
getArgs()           - [aoptest.Main@e53108]
getParameterTypes() - [class aoptest.Main]
aoptest.Main@e53108

adviceexecution() - その 16 : adviceexecution + thisJoinPoint - その 5

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	void around(Main main): target (main) && call( void Main.method() ) {
	}
}
public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	before(): adviceexecution() && !within(MyMainAspect) {

		println("getArgs()           - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		AdviceSignature sig = (AdviceSignature)thisJoinPoint.getSignature();

		println("getParameterTypes() - " + Arrays.asList( sig.getParameterTypes() ) );
	}

}
java> java -cp dest aoptest.Main
getArgs()           - [aoptest.Main@e53108, null]
getParameterTypes() - [class aoptest.Main, class org.aspectj.runtime.internal.AroundClosure]

adviceexecution() - その 17 : adviceexecution + thisJoinPoint - その 6

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {}
}
public aspect MainAspect {

	void around(Main main): target (main) && call( void Main.method() ) {
	}
}
public aspect MyMainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	void around(): adviceexecution() && !within(MyMainAspect) {

		println("getArgs()           - " + Arrays.asList( thisJoinPoint.getArgs() ) );

		AdviceSignature sig = (AdviceSignature)thisJoinPoint.getSignature();

		println("getParameterTypes() - " + Arrays.asList( sig.getParameterTypes() ) );
	}
}
java> java -cp dest aoptest.Main
getArgs()           - [aoptest.Main@19189e1, aoptest.Main$AjcClosure1@1f33675]
getParameterTypes() - [class aoptest.Main, class org.aspectj.runtime.internal.AroundClosure]

get(Signature)

get pointcut はフィールドアクセスに関連してきます。

get(Signature) - その 1

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
	
		System.out.println( new Main().getString() );
	}
	
	public String getString() {
		return str;
	}
}
public aspect MainAspect {

	before(): get( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
aaa

get(Signature) - その 2

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
		new Main().printString();
	}
	
	public void printString() {
		System.out.println(str);
	}
}
public aspect MainAspect {

	before(): get( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
aaa

get(Signature) - その 3

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
		new Main().tempString();
	}

	public void tempString() {
		String tmp = str;
	}
}
public aspect MainAspect {

	before(): get( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before

get(Signature) - その 4

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
		new Main().length();
	}
	
	public int length() {
		return str.length();
	}
}
public aspect MainAspect {

	before(): get( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before

get(Signature) - その 5 : get + around advice

(1.1rc1 OK)

この例では get pointcut と around advice の組み合わせた場合の例を紹介します。

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
		System.out.println( new Main().getString() );
	}
	
	public String getString() {
		return str;
	}
}
public aspect MainAspect {

	String around(): get( String Main.str ) {
		return "xxx";
	}
}
java> java -cp dest aoptest.Main
xxx

set(Signature)

set(Signature) - その 1

(1.1rc1 OK)

public class Main {

	private String str;

	public Main() {
		this.str = "aaa";
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): set( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before

set(Signature) - その 2

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): set( String Main.str ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before

set(Signature) - その 3 : set + args

(1.1rc1 OK)

public class Main {

	private String str;

	public Main() {
		this.str = "aaa";
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(String str): args(str) && set( String Main.str ) {
		System.out.println("before - " + str);
	}
}
java> java -cp dest aoptest.Main
before - aaa

set(Signature) - その 4 : set + around advice

(1.1rc1 OK)

public class Main {

	private String str;

	public Main() {

		this.str = "aaa";

		System.out.println(str);
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	void around(): set( String Main.str ) {
	}
}
java> java -cp dest aoptest.Main
null

set(Signature) - その 5 : set + args + around advice

(1.1rc1 OK)

public class Main {

	private String str;

	public Main() {

		this.str = "aaa";

		System.out.println(str);
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	void around(String str): args(str) && set( String Main.str ) {
		proceed("xxx");
	}
}
java> java -cp dest aoptest.Main
xxx

initialization(Signature)

initialization(Signature) - その 1

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): initialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()

initialization(Signature) - その 2

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
		new Main();
	}
}
public aspect MainAspect {

	before(): initialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()
before
Main()

initialization(Signature) - その 3 : initialization + around

(1.1rc1 OK)

この例では initialization と around advice の組み合わせを紹介します。initialization と around advice の組み合わせは、サポートはされていません。

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	void around(): initialization( Main.new() ) {
		System.out.println("around");
	}
}
java> java -cp dest aoptest.Main
Main()

initialization(Signature) - その 4 : initialization + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
import org.aspectj.lang.*;

public aspect MainAspect {

	before(): initialization( Main.new() ) {

		System.out.println("getTarget() - " + thisJoinPoint.getTarget() );
		System.out.println("getThis()   - " + thisJoinPoint.getThis() );

		Class decType = thisJoinPoint.getSignature().getDeclaringType();

		System.out.println("");

		System.out.println("getSignature().getDeclaringType() - " + decType);
	}
}
java> java -cp dest aoptest.Main
getTarget() - aoptest.Main@1bc4459
getThis()   - aoptest.Main@1bc4459

getSignature().getDeclaringType() - class aoptest.Main
call pointcut との比較:
public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): call( Main.new() ) {

		System.out.println("getTarget() - " + thisJoinPoint.getTarget() );
		System.out.println("getThis()   - " + thisJoinPoint.getThis() );

		Class decType = thisJoinPoint.getSignature().getDeclaringType();

		System.out.println("");

		System.out.println("getSignature().getDeclaringType() - " + decType);
	}
}
java> java -cp dest aoptest.Main
getTarget() - null
getThis()   - null

getSignature().getDeclaringType() - class aoptest.Main
execution pointcut との比較:
public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
import org.aspectj.lang.*;

public aspect MainAspect {

	before(): execution( Main.new() ) {

		System.out.println("getTarget() - " + thisJoinPoint.getTarget() );
		System.out.println("getThis()   - " + thisJoinPoint.getThis() );

		Class decType = thisJoinPoint.getSignature().getDeclaringType();

		System.out.println("");

		System.out.println("getSignature().getDeclaringType() - " + decType);
	}
}
java> java -cp dest aoptest.Main
getTarget() - aoptest.Main@1bc4459
getThis()   - aoptest.Main@1bc4459

getSignature().getDeclaringType() - class aoptest.Main

preinitialization(Signature)

preinitialization(Signature) - その 1 : preinitialization + before advice

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): preinitialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main
initialization との比較:
public aspect MainAspect {

	before(): initialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main

preinitialization(Signature) - その 2 : preinitialization + before advice

(1.1rc1 OK)

public abstract class AbstractMain {

	public AbstractMain() {
		System.out.println("AbstractMain");
	}
}
public class Main extends AbstractMain {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): preinitialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
AbstractMain
Main
initialization との比較:
public aspect MainAspect {

	before(): initialization( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
AbstractMain
before
Main

preinitialization(Signature) - その 3 : preinitialization + before advice

(1.1rc1 OK)

public abstract class AbstractMain {

	public AbstractMain() {
		System.out.println("AbstractMain");
	}
}
public class Main extends AbstractMain {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): preinitialization( AbstractMain.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
AbstractMain
Main
initialization との比較:
public aspect MainAspect {

	before(): initialization( AbstractMain.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
AbstractMain
Main

preinitialization(Signature) - その 4 : preinitialization + after advice

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	after(): preinitialization( Main.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
after
Main
initialization との比較:
public aspect MainAspect {

	after(): initialization( Main.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
Main
after

preinitialization(Signature) - その 5 : preinitialization + after advice

(1.1rc1 OK)

public abstract class AbstractMain {

	public AbstractMain() {
		System.out.println("AbstractMain");
	}
}
public class Main extends AbstractMain {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	after(): preinitialization( Main.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
after
AbstractMain
Main
initialization との比較:
public aspect MainAspect {

	after(): initialization( Main.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
AbstractMain
Main
after

preinitialization(Signature) - その 6 : preinitialization + after advice

(1.1rc1 OK)

public abstract class AbstractMain {

	public AbstractMain() {
		System.out.println("AbstractMain");
	}
}
public class Main extends AbstractMain {

	public Main() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	after(): preinitialization( AbstractMain.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
after
AbstractMain
Main
initialization との比較:
public aspect MainAspect {

	after(): initialization( AbstractMain.new() ) {
		System.out.println("after");
	}
}
java> java -cp dest aoptest.Main
AbstractMain
after
Main

staticinitialization(TypePattern)

staticinitialization(TypePattern) - その 1

(1.1rc1 OK)

public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
		new Main();
	}
}
public aspect MainAspect {

	before(): staticinitialization(Main) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()
Main()

staticinitialization(TypePattern) - その 2

(1.1rc1 OK)

public class Main {

	static {
		System.out.println("static");
	}

	public static void main(String[] args) {
	}
}
public aspect MainAspect {

	before(): staticinitialization(Main) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
static

staticinitialization(TypePattern) - その 3 : staticinitialization + around advice

(1.1rc1 OK)

public class Main {

	static {
		System.out.println("static");
	}

	public static void main(String[] args) {
	}
}
public aspect MainAspect {

	void around(): staticinitialization(Main) {
		System.out.println("around");
	}
}
java> java -cp dest aoptest.Main
around

staticinitialization(TypePattern) - その 4 : staticinitialization + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
	}
}
public aspect MainAspect {

	private void println(String str) {
		System.out.println(str);
	}

	before(): staticinitialization(Main) {
		println("thisJoinPoint             - " + thisJoinPoint);
		println("getSignature().getClass() - " + thisJoinPoint.getSignature().getClass()  );
	}
}

java> java -cp dest aoptest.Main
thisJoinPoint             - staticinitialization(aoptest.Main.<clinit>)
getSignature().getClass() - class org.aspectj.runtime.reflect.InitializerSignatureImpl

within(TypePattern)

within pointcut (と withincode pointcut) が、他の pointcut と異なる点の 1 つは、join point の場所が、実際のソースコード内に限定されることです。TypePattern で指定されたクラスのソースコード内での特定のポイント (join point) を選び出す、というのが within pointcut の雰囲気です。

within(TypePattern) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
	}
}
public aspect MainAspect {

	before(): within( Main ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
before

within(TypePattern) - その 2 : within + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
	}
}
public aspect MainAspect {

	before(): within( Main ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before - staticinitialization(aoptest.Main.)
before - execution(void aoptest.Main.main(String[]))

within(TypePattern) - その 3 : within + thisJoinPoint - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main(); // 単にコンストラクタの呼び出しを追加するだけで、
		            // within pointcut により、Main の中のどんな join point が
		            // 選び出されるのかを試す。
	}
}
public aspect MainAspect {

	before(): within( Main ) {
		System.out.println("before - " + thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
before - staticinitialization(aoptest.Main.)
before - execution(void aoptest.Main.main(String[]))
before - call(aoptest.Main())
before - preinitialization(aoptest.Main())
before - initialization(aoptest.Main())
before - execution(aoptest.Main())

within(TypePattern) - その 4 : within + thisJoinPoint - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): within( Main ) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - staticinitialization
       - staticinitialization(aj.Main.)

before - method-execution
       - execution(void aj.Main.main(String[]))

before - constructor-call
       - call(aj.Main())

before - preinitialization
       - preinitialization(aj.Main())

before - initialization
       - initialization(aj.Main())

before - constructor-execution
       - execution(aj.Main())

within(TypePattern) - その 5

(1.1rc1 OK)

public class MainClient {

	public MainClient() {
		System.out.println("MainClient()");
		new Main();
	}
}
public class Main {

	public Main() {
		System.out.println("Main()");
	}

	public static void main(String[] args) {
		new Main();
		new MainClient();
	}
}
public aspect MainAspect {

	before(): call( Main.new() ) && within( Main ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()
MainClient()
Main()
もし within pointcut を指定していなかったとしたら:
public aspect MainAspect {

	before(): call( Main.new() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()
MainClient()
before
Main()
しかし、もし call pointcut ではなく、execution pointcut を within pointcut と組み合わせていたとしたら:
public aspect MainAspect {

	before(): execution( Main.new() ) && within( Main ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
Main()
MainClient()
before // call pointcut と within との場合では、この出力がない
Main()

withincode(Signature)

withincode pointcut は within pointcut とほぼ同じような意味を持っています。within では TypePattern で指定された中でのすべての join point を選び出すという雰囲気のものですが、withincode pointcut では 指定された Signature に一致するメソッドやコンストラクタ内でのすべての join point を選び出すという雰囲気です。

withincode(Signature) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before(): withincode( void Main.method() ) {
		System.out.println("before");
	}
}
実行結果は以下のようになります。
java> java -cp dest aoptest.Main
before

withincode(Signature) - その 2 : withincode + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before(): withincode( void Main.method() ) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
	}
}
java> java -cp dest aoptest.Main
before - method-execution
       - execution(void aoptest.Main.method())

withincode(Signature) - その 3 : withincode + thisJoinPoint

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	before(): withincode( void Main.method() ) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - method-execution
       - execution(void aoptest.Main.method())

before - field-get
       - get(PrintStream java.lang.System.out)

before - method-call
       - call(void java.io.PrintStream.println(String))

method

cflow(Pointcut)

cflow(Pointcut) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method() );

	before(): cflow( methodCall() ) && !within(MainAspect) {
		System.out.println("before");
	}

}
java> java -cp dest aoptest.Main
before
before
before
before
method

cflow(Pointcut) - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method() );

	before(): cflow( methodCall() ) && !within(MainAspect) {
		System.out.println("before - " + thisJoinPoint);
	}

}
java> java -cp dest aoptest.Main
before - call(void aoptest.Main.method())
before - execution(void aoptest.Main.method())
before - get(PrintStream java.lang.System.out)
before - call(void java.io.PrintStream.println(String))
method
cflowbelow との比較:
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method() );

	before(): cflowbelow( methodCall() ) && !within(MainAspect) {
		System.out.println("before - " + thisJoinPoint);
	}

}
java> java -cp dest aoptest.Main
before - execution(void aoptest.Main.method())
before - get(PrintStream java.lang.System.out)
before - call(void java.io.PrintStream.println(String))
method

cflow(Pointcut) - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() {
		print("method");
	}

	private void print(String str) {
		System.out.println(str);
	}
}
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method() );

	before(): cflow( methodCall() ) && call( void Main.print(String) ) {
		System.out.println("before - " + thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
before - call(void aoptest.Main.print(String))
method

cflowbelow(Pointcut)

cflowbelow と cflow は、ほとんど同じです。違いは cflow が指定された join point を選び出すのに対して、cflowbelow は、そうしない、ということです。

AspectJ FAQ」の「What is the difference between cflow and cflowbelow?」では、この二つの pointcut designator の違いを解説しています。

このドキュメントでは cflow の「例その 2」で cflow と cflowbelow の結果の違いを紹介しています。

1 つの混乱する点は、もし特定の join point が再起的に選び出されるような状況だと、どうなのか、ということです。以下の例では、cflowbelow と cflow の違いは、一番最初に選び出される join point を含むか含まないかの違い、ということを示します。

cflowbelow(Pointcut) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().method(false);
	}

	public void method(boolean b) {
		if (b) {
			System.out.println("method");
		} else {
			method(true);
		}
	}
}
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method(boolean) );

	before(): cflowbelow( methodCall() ) && !within(MainAspect) {
		System.out.println("before - " + thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
before - execution(void aoptest.Main.method(boolean))
before - call(void aoptest.Main.method(boolean))
before - execution(void aoptest.Main.method(boolean))
before - get(PrintStream java.lang.System.out)
before - call(void java.io.PrintStream.println(String))
method
cflow との比較:
public aspect MainAspect {

	pointcut methodCall() : call( void Main.method(boolean) );

	before(): cflow( methodCall() ) && !within(MainAspect) {
		System.out.println("before - " + thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
before - call(void aj.Main.method(boolean)) // cflowbelow では、この join point を選び出さない
before - execution(void aj.Main.method(boolean))
before - call(void aj.Main.method(boolean))
before - execution(void aj.Main.method(boolean))
before - get(PrintStream java.lang.System.out)
before - call(void java.io.PrintStream.println(String))
method

this(TypePattern or Id)

this(TypePattern or Id) : その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): this(Main) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
before

this(TypePattern or Id) : その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): this(Main) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - initialization
       - initialization(aoptest.Main())

before - constructor-execution
       - execution(aoptest.Main())

this(TypePattern or Id) : その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(Main main): this(main) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
aoptest.Main@1a8c4e7
aoptest.Main@1a8c4e7

this(TypePattern or Id) : その 4

(1.1rc1 OK)

public class AbstractMain { // "Abstract" なのに abstract で宣言されていないのは
                            // 単に "Main" のスーパクラスという目的だから
}
public class Main extends AbstractMain {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): this(Main) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("       - " + thisJoinPoint.getThis() + " (this)");
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - initialization
       - initialization(aoptest.AbstractMain())
       - aoptest.Main@4a5ab2 (this)

before - constructor-execution
       - execution(aoptest.AbstractMain())
       - aoptest.Main@4a5ab2 (this)

before - initialization
       - initialization(aoptest.Main())
       - aoptest.Main@4a5ab2 (this)

before - constructor-execution
       - execution(aoptest.Main())
       - aoptest.Main@4a5ab2 (this)

this(TypePattern or Id) : その 5

(1.1rc1 OK)

public class AbstractMain {
}
public class Main extends AbstractMain {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(): this(AbstractMain) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("       - " + thisJoinPoint.getThis() + " (this)");
		System.out.println("");
	}
}

java> java -cp dest aoptest.Main
before - initialization
       - initialization(aoptest.AbstractMain())
       - aoptest.Main@4a5ab2 (this)

before - constructor-execution
       - execution(aoptest.AbstractMain())
       - aoptest.Main@4a5ab2 (this)

before - initialization
       - initialization(aoptest.Main())
       - aoptest.Main@4a5ab2 (this)

before - constructor-execution
       - execution(aoptest.Main())
       - aoptest.Main@4a5ab2 (this)

target(TypePattern or Id)

target(TypePattern or Id) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before() : target(Main) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
before

target(TypePattern or Id) - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before() : target(Main) {
		
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - initialization
       - initialization(aoptest.Main())

before - constructor-execution
       - execution(aoptest.Main())

target(TypePattern or Id) - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(Main main) : target(main) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
aoptest.Main@1a8c4e7
aoptest.Main@1a8c4e7

target(TypePattern or Id) - その 4

(1.1rc1 OK)

public class AbstractMain { }
public class Main extends AbstractMain {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before(AbstractMain main) : target(main) {
		System.out.println(main);
	}
}
java> java -cp dest aoptest.Main
aoptest.Main@1172e08
aoptest.Main@1172e08
aoptest.Main@1172e08
aoptest.Main@1172e08

target(TypePattern or Id) - その 5

(1.1rc1 OK)

public class AbstractMain { }
public class Main extends AbstractMain {

	public static void main(String[] args) {
		new Main();
	}
}
public aspect MainAspect {

	before() : target(AbstractMain) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - initialization
       - initialization(aoptest.AbstractMain())

before - constructor-execution
       - execution(aoptest.AbstractMain())

before - initialization
       - initialization(aoptest.Main())

before - constructor-execution
       - execution(aoptest.Main())

args(TypePattern or Id, ...)

args(TypePattern or Id, ...) - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) { }
}
public aspect MainAspect {

	before() : args(int) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
before
before

args(TypePattern or Id, ...) - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) { }
}
public aspect MainAspect {

	before() : args(int) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - method-call
       - call(void aoptest.Main.setInt(int))

before - method-execution
       - execution(void aoptest.Main.setInt(int))

args(TypePattern or Id, ...) - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) { }
}
public aspect MainAspect {

	before(int i) : args(i) && !within(MainAspect) {
		System.out.println("before - " + i );
	}
}
java> java -cp dest aoptest.Main
before - 10
before - 10

args(TypePattern or Id, ...) - その 4

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) { }
}
public aspect MainAspect {

	before() : args(int) && call( void Main.setInt(int) ) {
		System.out.println("before - " + thisJoinPoint.getKind() );
		System.out.println("       - " + thisJoinPoint );
		System.out.println("");
	}
}
java> java -cp dest aoptest.Main
before - method-call
       - call(void aj.Main.setInt(int))

args(TypePattern or Id, ...) - その 5

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) {
		System.out.println(i);
	}
}
public aspect MainAspect {

	void around() : args(int) && call( void Main.setInt(int) ) {
		System.out.println("around");
		proceed();
	}
}
java> java -cp dest aoptest.Main
around
10

args(TypePattern or Id, ...) - その 6

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {
		new Main().setInt(10);
	}
	
	public void setInt(int i) {
		System.out.println(i);
	}
}
public aspect MainAspect {

	void around(int i) : args(i) && call( void Main.setInt(int) ) {
		proceed(i + i);
	}
}
java> java -cp dest aoptest.Main
20

args(TypePattern or Id, ...) - その 7

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().setObject( new Integer(10) );
		new Main().setObject("aaa");
	}
	
	public void setObject(Object obj) { }
}
public aspect MainAspect {

	pointcut setObject() : call( void Main.setObject(Object) );

	before() : args(Integer) && setObject() {
		System.out.println("before - Integer");
	}

	before() : args(String) && setObject() {
		System.out.println("before - String");
	}
}
java> java -cp dest aoptest.Main
before - Integer
before - String

if(BooleanExpression)

if(BooleanExpression) - その 1

(1.1.1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		main.method();
		main.method();
	}
	
	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect {

	private static boolean isCalled;

	after() : call( void Main.method() ) {
		isCalled = true;
	}

	void around() : call( void Main.method() ) && if (isCalled) { }
}
java> java -cp dest aoptest.Main
method

if(BooleanExpression) - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		try {
			new Main().setString(null);

		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void setString(String str) { }
}
public aspect MainAspect {

	before(String str) :
		call( void Main.setString(String) ) &&
		args(str) &&
		if (str == null)
	{
		throw new IllegalArgumentException();
	}
}
java> java -cp dest aoptest.Main
java.lang.IllegalArgumentException

if(BooleanExpression) - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		try {
			new Main().setString(null);

		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void setString(String str) { }
}
public aspect MainAspect {

	before(String str) :
		call( void Main.setString(String) ) &&
		args(str) &&
		if ( isNull(str) )
	{
		throw new IllegalArgumentException();
	}

	private static boolean isNull(Object obj) {
		return obj == null;
	}
}
java> java -cp dest aoptest.Main
java.lang.IllegalArgumentException

if(BooleanExpression) - その 4

(1.1rc1 OK)

public class Main {

	private String str;

	public Main(String str) {
		this.str = str;
	}

	public static void main(String[] args) {

		try {
			new Main(null).printString();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public String getString() {
		return str;
	}

	public void printString() {
		System.out.println(str);
	}
}
public aspect MainAspect {

	before(Main main) :
		call( void Main.printString() ) &&
		target(main) &&
		if ( main.getString() == null )
	{
		throw new IllegalStateException();
	}
}
java> java -cp dest aoptest.Main
java.lang.IllegalStateException

if(BooleanExpression) - その 5

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		try {
			new Main().setString(null);

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void setString(String str) { }
}
public aspect MainAspect {

	before() :
		call( void Main.setString(String) ) &&
		if ( thisJoinPoint.getArgs()[0] == null )
	{
		throw new IllegalArgumentException();
	}
}
java> java -cp dest aoptest.Main
java.lang.IllegalArgumentException

if(BooleanExpression) - その 6

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before() : call( void Main.method() ) && if ( printJP(thisJoinPoint) ) {
	}

	private static boolean printJP(JoinPoint jp) {
		System.out.println(jp);
		return false;
	}
}
java> java -cp dest aoptest.Main
call(void aoptest.Main.method())

if(BooleanExpression) - その 7

(1.1.1 OK)

この例では、if pointcut 内では new ですら使えることを示します。ただし、実践的にどのような場合に使う機会があるのかは分かりません。

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		main.method();
	}
	
	public void method() {
		System.out.println("Main.method()");
	}
}
public aspect MainAspect {

	before() :
		call( void Main.method() ) &&
		if ( new Inner() != null ) // 単に new が使えることを示すだけ
	{
		System.out.println("after");
	}
	
	private static class Inner {
		public Inner() {
			System.out.println("Inner.Inner()");
		}
	}
}
java> java -cp dest aoptest.Main
Inner.Inner()
after
Main.method()

その他 : アスペクトへの適用

(1.1rc1 OK)

アスペクトを適用する対象としては、通常のクラスだけに制限されるわけではなく、アスペクトに対しても同様に可能です:

public class Main {

	public static void main(String[] args) {
		new Main().method();
	}

	public void method() { }
}
public aspect MainAspect {

	before() : call( void Main.method() ) {
		printBefore();
	}
	
	private void printBefore() {
		System.out.println("before");
	}
}
public aspect MainAspectAspect {

	before() : call( void MainAspect.printBefore() ) {
		System.out.println("MainAspectAspect - before");
	}
}
java> java -cp dest aoptest.Main
MainAspectAspect - before
before

[
TOP ]

更新履歴

todo