Last Updated : 2004/4/3
asato <asato@ncfreak.com>
[ TOP ]
Pointcut Designators (Pointcuts)
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)
以下のようなプリミティブな 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)
組み合わせる pointcut | advice | 利用度 | コメント |
call のみ | before | ○ | メソッドやコンストラクタの呼び出し 前 に何らかの処理を行うコードを書くことができます。 |
after | ○ | メソッドやコンストラクタの呼び出し 後 に何らかの処理を行うコードを書くことができます。 | |
around | ○ | メソッドやコンストラクタの呼び出しの 前後 に何らかの処理を行うコードを書くことができます。さらには、オリジナルのメソッドやコンストラクタの呼び出しとは全く別のコードで置き換えることも可能です (メソッドが戻り値を伴っている場合は、同じ戻り値の型でリターンする必要があります)。 |
以下の節では、call pointcut を使った、次のような例を紹介します:
call(Signature) - その 1: メソッドに対して - その 1: call + before advice
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
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 + 例外
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 + 例外
例外をスローするメソッドに対して、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 + 戻り値へのアクセス
もし、あるメソッドが特定の戻り値を返すのであれば、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 + 例外
例外をスローするメソッドに対して、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 + 例外 + 例外オブジェクトへのアクセス
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
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
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
この例では、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: 既存ライブラリに対しては?
今までの例では、独自に作ったクラスに対しての 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 との組み合わせ
この例では 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 との組み合わせ
この例では 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
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()
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
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 : ポリモーフィズムを伴う場合 (スーパークラスのメソッドに対して)
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 : ポリモーフィズムを伴う場合 (サブクラスのメソッドに対して)
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 : ポリモーフィズムを伴う場合 - 存在しないメソッド
この例は、例 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 helloadvice が実行されて いない ことに注意してください。この結果は、例 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
この例とこの次のいくつかの例では、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
この例は、どこで 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
ここでは、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(Signature) - その 1 : メソッドに対して
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 : 既存のライブラリに対して
この例では既存のライブラリ (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
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
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: 既存のライブラリに対して
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
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 : 既存のライブラリに対して
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
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
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(TypePattern) - その 1
この例では、例外をスローするメソッドとして 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 との組み合わせ
この例では、前の例では 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 との組み合わせ
次は、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
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
もし 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 : 例外オブジェクトへのアクセス
この例では 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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(Signature) - その 1
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
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
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
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
この例では 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
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
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
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
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
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
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
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
この例では 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
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.Maincall 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.Mainexecution 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
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 Maininitialization との比較:
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
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 Maininitialization との比較:
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
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 Maininitialization との比較:
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
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 Maininitialization との比較:
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
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 Maininitialization との比較:
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
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 Maininitialization との比較:
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
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
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
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
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(TypePattern) - その 1
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
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
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
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
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(Signature) - その 1
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
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
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
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
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)) methodcflowbelow との比較:
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
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)
「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
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)) methodcflow との比較:
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
この例では、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()
その他 : アスペクトへの適用
アスペクトを適用する対象としては、通常のクラスだけに制限されるわけではなく、アスペクトに対しても同様に可能です:
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
after() returning(JLabel comp) : call( JLabel.new(..) )は OK でも
after(JLabel label) : target(label) && call( JLabel.new(..) )はダメ