AspectJ 環境を構築しよう

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

[ TOP ]

アスペクト関連

この章では、アスペクトに関連のある事柄をサンプルコードとともに紹介します。それらは: などです。

これらアスペクトに関連のある事柄についての正確な情報源やサンプルコードが見つけられる場所としては The AspectJ Programming Guide を参照してください。特に、ここで扱っている事柄に関連のあるページとしては:

があります。

アスペクトの拡張 (extend)

アスペクトは、クラスを拡張 (あるいは継承。以下では、拡張と継承を同じ意味で使用します) するときに 似た 雰囲気で拡張 (extend) することができます。あるアスペクトを拡張することによって継承されるものは、フィールド、メソッド、アスペクト内で宣言された interface やクラス、そして、アスペクト特有のものである pointcut です。

アスペクトの継承を考える場合、1 つ注意する点があります: それは、クラスの継承と違ってアスペクトの継承では、抽象アスペクト のみ の継承が許されているということです。もし、具象アスペクト (abstract で宣言されていないアスペクト) を継承しようとすると、それはコンパイル時にエラーとなります:

public aspect ConcreteAspect { }

public aspect ConcreteAspect extends ConcreteAspect { } // コンパイルエラー!
                                                                 // 抽象アスペクトでないアスペクトは
                                                                 // 継承できない


public abstract aspect AbstractAspect { }

public aspect ConcreteAspect extends AbstractAspect { } // OK

また、アスペクトは、具象アスペクト、抽象アスペクトにかかわらず、通常のクラスを継承したり、interface を実装することも許されています:

public interface Observer { }

public aspect ConcreteAspect implements Observer { } // OK
以下の節では、これらアスペクトの拡張に関連のある、より具体的なサンプルコードを紹介します。

アスペクトの拡張 - その 1 : アスペクトの継承

(1.1rc1 OK)

public abstract aspect AbstractAspect { }
public aspect ConcreteAspect extends AbstractAspect { }

アスペクトの拡張 - その 2 : アスペクトの継承

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

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

	protected pointcut method() : call( void Main.method() );
}
public aspect MainAspect extends AbstractMainAspect {

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

pointcut 再利用のその他のアプローチ

pointcut のみを再利用したいのであれば継承する必要なく実現可能なアプローチもあります:
public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

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

	before() : MainAspect.method() {
		System.out.println("before");
	}

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

アスペクトの拡張 - その 3 : アスペクトの継承

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

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

	protected abstract pointcut method();
	
	before() : method() {
		System.out.println("before");
	}
}
public aspect MainAspect extends AbstractMainAspect {

	protected pointcut method() : call( void Main.method() );
}
java> java -cp dest aoptest.Main
before
Hello!

aspectOf()

aspectOf() メソッドは、アスペクトのインスタンスを得るための static なメソッドです。

aspectOf() - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		MainAspect aspect = MainAspect.aspectOf();

		System.out.println( aspect );
	}
}
public aspect MainAspect { }
java> java -cp dest aoptest.Main
aoptest.MainAspect@1a8c4e7
抽象アスペクトに対しての aspectOf: 抽象アスペクトに対しての aspectOf() メソッドの呼び出しは、できません。コンパイル時にエラーとなります:
public class Main {

	public static void main(String[] args) {

		MainAspect aspect = MainAspect.aspectOf(); // コンパイルエラー

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

aspectOf() - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		main.method();


		MainAspect.aspectOf().setBeforeMessage("before before");

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

	private String message = "before";

	public void setBeforeMessage(String message) {
		this.message = message;
	}

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

Aspect privilege

Aspect privilege - その 1 : private なフィールド

(1.1rc1 OK)

public class Main {

	private String str = "aaa";

	public static void main(String[] args) {

		MainAspect.printString( new Main() );
	}
}
privileged aspect MainAspect {

	public static void printString(Main main) {

		System.out.println( main.str );
	}
}
java> java -cp dest aoptest.Main
aaa

Aspect privilege - その 2 : private なメソッド

public class Main {

	public static void main(String[] args) {

		MainAspect.callMethod( new Main() );
	}
	
	private void method() {
		System.out.println("method");
	}
}
privileged aspect MainAspect {

	public static void callMethod(Main main) {

		main.method();
	}
}
java> java -cp dest aoptest.Main
method

Advice Precedence

Advice Precedence

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}
	
	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspectA {

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

	before() : call( void Main.method() ) {
		System.out.println("before - MainAspectB");
	}
}
public aspect MainAspect {
	declare precedence : MainAspectA, MainAspectB;
}
java> java -cp dest aoptest.Main
before - MainAspectA
before - MainAspectB
method
もし precedence 宣言の順番を入れ替えたとするなら:
public aspect MainAspect {
	declare precedence : MainAspectB, MainAspectA;
}
実行結果は:
java> java -cp dest aoptest.Main
before - MainAspectB
before - MainAspectA
method

perthis

perthis - その 1

(1.1rc1 OK)

public class Main {

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08

perthis - その 2

(1.1rc1 OK)

public class Main {

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

	public static void main(String[] args) {

		new Main();
	}
}
public aspect MainAspect perthis( this(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
Main()

perthis - その 3 : aspectOf

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		System.out.println( MainAspect.aspectOf( main ) );
	}
}
public aspect MainAspect perthis( this(Main) ) {

	public MainAspect() {
		System.out.println("MainAspect() - " + this);
	}
}
java> java -cp dest aoptest.Main
MainAspect() - aoptest.MainAspect@1172e08
aoptest.MainAspect@1172e08

perthis - その 4

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
		new Main();
	}
}
public aspect MainAspect perthis( this(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@cf2c80

perthis - その 5

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		main.method();
	}

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

	private pointcut method() : execution( void Main.method() );

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
method

perthis - その 6 : NoAspectBoundException

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		System.out.println("aspectOf() - " + MainAspect.aspectOf(main) );
	}

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

	private pointcut method() : execution( void Main.method() );

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
Exception in thread "main" org.aspectj.lang.NoAspectBoundException
        at aoptest.MainAspect.aspectOf(MainAspect.java)
        at aoptest.Main.main(Main.java:12)

perthis - その 7 : perthis + execution

(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 perthis( this(Main) ) {

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

perthis - その 8 : perthis + call

(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 perthis( this(Main) ) {

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

perthis - その 9 : perthis + call

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {
		printMethod();
	}

	private void printMethod() {
		System.out.println("method");
	}
}
public aspect MainAspect perthis( this(Main) ) {

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

perthis - その 10

(1.1rc1 OK)

public class YourMain {

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

	public static void main(String[] args) {

		new YourMain().method();
	}
}
public aspect MainAspect perthis( this(Main) ) {

	before() : call( void YourMain.method() ) || execution( void YourMain.method() ) {

		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
YourMain - method

perthis - その 11

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main = new Main();

		main.method();
		main.method();

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

	private int count;

	after() : execution( void Main.method() ){
		count++;
	}

	public void printCount() {
		System.out.println("count: " + count);
	}
}
java> java -cp dest aoptest.Main
method
method
count: 2

perthis - その 12

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		Main main1 = new Main();

		main1.method();

		MainAspect.aspectOf(main1).printCount();


		Main main2 = new Main();

		main2.method();

		MainAspect.aspectOf(main2).printCount();

	}
	
	public void method() {
		System.out.println("method");
	}
}
public aspect MainAspect perthis( this(Main) ) { // 変更なし

	private int count;

	after() : execution( void Main.method() ){
		count++;
	}

	public void printCount() {
		System.out.println("count: " + count);
	}
}
java> java -cp dest aoptest.Main
method
count: 1
method
count: 1

pertarget

pertarget - その 1

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
	}
}
public aspect MainAspect pertarget( this(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08

pertarget - その 2

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
	}
}
public aspect MainAspect pertarget( target(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08

pertarget - その 3

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
		new Main();
	}
}
public aspect MainAspect pertarget( this(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@cf2c80

pertarget - その 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 pertarget( target(Main) ) {

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

pertarget - その 5

(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 pertarget( this(Main) ) {

	before() : call( void Main.method() ) {
		System.out.println("before");
	}
}
// 横に長いので改行 (\ で改行場所を示している) しています
java> java -cp dest aoptest.Main
Exception in thread "main" java.lang.VerifyError: \
(class: aoptest/Main, method: methd signature: ()V) \
Unable to pop operand off an empty stack

pertarget - その 6

(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 pertarget( target(Main) ) {

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

pertarget - その 7

(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 pertarget( this(Main) ) {

	before() : execution( void Main.method() ) {
		System.out.println("before");
	}
}
// 横に長いので改行 (\ で改行場所を示している) しています
java> java -cp dest aoptest.Main
Exception in thread "main" java.lang.VerifyError: \
(class: aoptest/Main, method: methd signature: ()V) \
Unable to pop operand off an empty stack

pertarget - その 8 : pointcut = call

(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 pertarget( method() ) {

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

	public MainAspect() {
		System.out.println(this);
	}
}
// 横に長いので改行 (\ で改行場所を示している) しています
java> java -cp dest aoptest.Main
Exception in thread "main" java.lang.VerifyError: \
(class: aoptest/Main, method: mainsignature: ([Ljava/lang/String;)V) \
Unable to pop operand off an empty stack

pertarget - その 9 : pointcut = execution

(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 pertarget( method() ) {

	private pointcut method() : execution( void Main.method() );

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
method

percflow

percflow - その 1 : pointcut = this

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
	}
}
public aspect MainAspect percflow( this(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@6eb38a

percflow - その 2 : pointcut = target

(1.1rc2 OK)

public class Main {

	public static void main(String[] args) {

		new Main();
	}
}
public aspect MainAspect percflow( target(Main) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@6eb38a

percflow - その 3 : : pointcut = call

(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 percflow( call( void Main.method() ) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
method

percflow - その 4

(1.1rc1 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 percflow( call( void Main.method() ) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
method
aoptest.MainAspect@6eb38a
method

percflow - その 5 : aspectOf()

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {

		System.out.println("aspectOf - " + MainAspect.aspectOf() );

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aspectOf - aoptest.MainAspect@1172e08
method

percflow - その 6 : aspectOf()

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {

		System.out.println("aspectOf - " + MainAspect.aspectOf() );

		printMethod();
	}

	private void printMethod() {

		System.out.println("aspectOf - " + MainAspect.aspectOf() );

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aspectOf - aoptest.MainAspect@1172e08
aspectOf - aoptest.MainAspect@1172e08
method

percflow - その 7 : aspectOf()

(1.1rc2 OK)

public class YourMain {

	public void method() {

		System.out.println("aspectOf - " + MainAspect.aspectOf() );

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

	public static void main(String[] args) {

		new Main().method();
	}

	public void method() {
		new YourMain().method();
	}
}
public aspect MainAspect percflow( call( void Main.method() ) ) {

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aspectOf - aoptest.MainAspect@1172e08
YourMain - method

percflow - その 8 : NoAspectBoundException

(1.1rc1 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();

		System.out.println("aspectOf - " + MainAspect.aspectOf() );
	}

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
method
Exception in thread "main" org.aspectj.lang.NoAspectBoundException
        at org.aspectj.runtime.internal.CFlowStack.peekInstance(CFlowStack.java:88)
        at aoptest.MainAspect.aspectOf(MainAspect.java)
        at aoptest.Main.main(Main.java:12)

percflow - その 9 :

(1.1rc2 OK)

public abstract class AbstractMain {
	public abstract void method();
}
public class Main extends AbstractMain {

	public static void main(String[] args) {

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

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@cf2c80
method

percflow - その 10 :

(1.1rc2 OK)

public class Main {

	public static void main(String[] args) {

		new Main().method();
	}

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

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

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

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

percflow - その 11 : インスタンスはいつ生成されるか?

(1.1rc2 OK)

public class Main { // 変更なし

	public static void main(String[] args) {

		new Main().method();
	}

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

	public MainAspect() {
		System.out.println(this);
	}
}
public aspect MainMethodAspect { // 変更なし

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

percflow - その 12 : advice の適用範囲 - その 1

(1.1rc2 OK)

public class YourMain {

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

	public static void main(String[] args) {

		new YourMain().method();
	}

	public void method() { }
}
public aspect MainAspect percflow( call( void Main.method() ) ) {

	public MainAspect() {
		System.out.println(this);
	}
	
	before() : call( void YourMain.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
YourMain - method
もし percflow を使用していないとしたら:
public aspect MainAspect {

	public MainAspect() {
		System.out.println(this);
	}
	
	before() : call( void YourMain.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
before
YourMain - method

percflow - その 13 : advice の適用範囲 - その 2

(1.1rc2 OK)

public class YourMain {

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

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

	public void method() {
		new YourMain().method();
	}
}
public aspect MainAspect percflow( call( void Main.method() ) ) {

	public MainAspect() {
		System.out.println(this);
	}
	
	before() : call( void YourMain.method() ) {
		System.out.println("before");
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
before
YourMain - method

percflowbelow

percflowbelow - その 1 : pointcut = this

(1.1rc2 OK)

public class Main {

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@6eb38a

percflowbelow - その 2 : pointcut = target

(1.1rc2 OK)

public class Main {

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

	public MainAspect() {
		System.out.println(this);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@1172e08
aoptest.MainAspect@6eb38a

percflowbelow - その 3 :

(1.1rc2 OK)

public class Main {

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

	public MainAspect() {
		System.out.println(this);
	}

	before() : target(Main) {
		System.out.println(thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@4a5ab2
execution(aoptest.Main())
aoptest.MainAspect@e53108
percflow との比較:
public aspect MainAspect percflow( target( Main ) ) {

	public MainAspect() {
		System.out.println(this);
	}

	before() : target(Main) {
		System.out.println(thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
aoptest.MainAspect@12b6651
initialization(aj.Main())
aoptest.MainAspect@e53108
execution(aj.Main())

percflowbelow - その 4 :

(1.1rc2 OK)

public class Main {

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

	before() : target(Main) {
		System.out.println(thisJoinPoint);
	}
}
java> java -cp dest aoptest.Main
execution(void aoptest.Main.method())
method
percflow との比較:
public aspect MainAspect percflow( call( void Main.method() ) ) {

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

アスペクトのインスタンス化

(1.1.1 OK)

通常、アスペクトのインスタンス化は new を使ってはできませんが、もし、アスペクトが privileged として宣言されているのであれば、アスペクトをインスタンス化することはできます(しかし、これはバグの可能性があります):

public class Main {
	public static void main(String[] args) {

		System.out.println("aspectOf()   : " + InnerAspect.aspectOf() );
		System.out.println("newInstance(): " + InnerAspect.newInstance() );
		System.out.println("newInstance(): " + InnerAspect.newInstance() );
	}

	privileged private static aspect InnerAspect {

		public static InnerAspect newInstance() {
			return new InnerAspect();
		}
	}
}
aspectOf()   : aoptest.Main$InnerAspect@1c78e57
newInstance(): aoptest.Main$InnerAspect@5224ee
newInstance(): aoptest.Main$InnerAspect@f6a746
しかし、問題点は advice 内での this は aspectOf() で取得できるインスタンスにバインドされることです。たとえば、一つのインスタンスに一つのアスペクトを割り当てたいようなケースを考えて見てください:
public class MyClass {
	public void method() {
		System.out.println("MyClass.method()");
	}
}
public class Main {

	public static void main(String[] args) {

		MyClass my1 = new MyClass();
		MyClass my2 = new MyClass();

		InnerAspect.newInstance(my1);
		InnerAspect.newInstance(my2);

		my1.method();
	}

	privileged private static aspect InnerAspect {
	
		private MyClass my;
	
		public static InnerAspect newInstance(MyClass my) {
			InnerAspect instance = new InnerAspect();
			instance.my = my;
			return instance;
		}
		
		before() : call( void MyClass.method() ) {
			System.out.println(this + " - " + my);
		}
	}
}
実行結果は:
aoptest.Main$InnerAspect@5224ee - null
MyClass.method()
一つの解決策は:
public class Main {

	public static void main(String[] args) {

		MyClass my1 = new MyClass();
		MyClass my2 = new MyClass();


		System.out.println("my1: " + my1);
		System.out.println("my2: " + my2);

		System.out.println();


		System.out.println( InnerAspect.newInstance(my1) );
		System.out.println( InnerAspect.newInstance(my2) );

		System.out.println();


		my1.method();
	}

	privileged private static aspect InnerAspect {
	
	
		private MyClass my;
	
		public static InnerAspect newInstance(MyClass my) {
			InnerAspect instance = new InnerAspect();
			instance.my = my;

			return instance;
		}
		
		before() : call( void MyClass.method() ) {
			System.out.println(this + " - " + my);
		}
		
		
	}

	privileged private static aspect InnerAspectAspect {

		private static List aspects = new ArrayList();
	
		InnerAspect around() : call(InnerAspect InnerAspect.newInstance(MyClass) ) {
			InnerAspect instance = proceed();
			aspects.add( instance );
		
			return instance;
		}
		
		void around(InnerAspect instance) :
			target(instance) && adviceexecution() && !within(InnerAspectAspect) 
		{

			for(Iterator itr = aspects.iterator() ; itr.hasNext(); ) {
				proceed( (InnerAspect)itr.next() );
			}
		}
	}
}
実行結果は:
my1: aoptest.MyClass@1ac04e8
my2: aoptest.MyClass@765291

aoptest.Main$InnerAspect@1004901
aoptest.Main$InnerAspect@1b90b39

aoptest.Main$InnerAspect@1004901 - aoptest.MyClass@1ac04e8
aoptest.Main$InnerAspect@1b90b39 - aoptest.MyClass@765291
MyClass.method()
ただし、around adivce を扱う場合(たとえば InnerAspect に around adivce がある場合)は、もう少し複雑になります。

[
TOP ]

更新履歴

todo