Aspectj in Action: 第一版に載ってた、Participant パターンについて。
class ClassA {
public void foo() {
System.out.println("ClassA.foo() called");
}
public void bar() {
System.out.println("ClassA.bar() called");
}
}
public class App {
public static void main(String[] args) {
ClassA a = new ClassA();
a.foo();
a.bar();
}
}
上のコードに作用して、以下のように星印をつけてコンソール出力を修飾する Star アスペクトがあるとする。
アスペクト適用なし | | Star アスペクト適用 |
ClassA.foo() called
ClassA.bar() called
| ⇒ | ★ClassA.foo() called
ClassA.bar() called
|
上の例では★がついているのは ClassA.foo() だが、後々の拡張性を考えて、どのメソッドが★印修飾されるかについて、アスペクト定義の側にはハードコードしたくない。また、後で★印修飾を適用するメソッドは、ジョインポイントにマッチさせるためのシグネーチャの制約(例えば命名規約だとか)をつけたくない。こういう状況で、Participant パターンが適用できる。
まず以下のように抽象アスペクトを定義する
public abstract aspect Star {
public abstract pointcut needStar();
Object around() : needStar() {
System.out.print("★");
return proceed();
}
}
次に、ClassA のクラス定義内で具象アスペクトを定義する。
class ClassA {
public static aspect StarForA extends Star {
public pointcut needStar(): call(void ClassA.foo());
}
public void foo() {
...略
}
こんな風にして、上図右のような★印修飾がついたコンソール出力が得られる。
さて、後でClassB を追加して、App.main() を以下のように変更したとする
public static void main(String[] args) {
ClassA a = new ClassA();
ClassB b = new ClassB();
a.foo();
a.bar();
b.baz();
}
ここで、メソッド baz() にも★印修飾を与えたい場合、以下のように書けばよい。
class ClassB {
public static aspect StarForB extends Star {
public pointcut needStar(): call(void ClassB.baz());
}
public void baz() {
System.out.println("ClassB.baz() called");
}
}
こうすれば、Starアスペクトへの変更も、baz() へのシグネーチャ制約も無く、以下のような出力が得られる。
★ClassA.foo() called
ClassA.bar() called
★ClassB.baz() called
■所感
0 件のコメント:
コメントを投稿