2006/09/14

[aspectj-users] 特定のアノテーションを持つメソッドをもつクラスを指定したい

[aspectj-users] Annotations injection on types based on methods annotations

特定のアノテーションを持つメソッドを持つクラスを指定して、アノテーションを付加したい、って話。
WhiteDogでもこれができると@WhiteDogClassがいらなくなってちょっと楽。

結論としては、今は出来ないけど、最新版ではundocumentedなhasmethod、hasfieldってポイントカットが用意してあるらしい。

使い方は、コマンドラインオプションに-XhasMemberを指定した上で、以下のように記述:

-- 引用 --
public aspect LiftImmutability {
declare @type:
hasmethod(@Immutable * *(..)):
@Container;
}
----

まだITDを考慮してなくて正式サポートじゃないけど、これ使えるとちょっと記述の幅が広がるなぁ。
いい感じ。

2006/09/01

[aspectj-users] syntheticメソッドを指定したい

[aspectj-users] Excluding synthetic compiler methods

Javaコンパイラが生成するメソッドにsynthetic属性が付くのは周知だけど(嘘ですごめんなさい。この投稿で初めて知りました)、ポイントカットにそれを指定したいという話。
もしそこまでやるんだと、バイトコードレベルでのポイントカットをクリアにする必要性が出てくるなぁ。

投稿した人は、AspectJがsyntheticメソッドまでポイントカットの対象としていることを問題視して、それを省くために指定したいということだったんだけど、結局、その振る舞いはバグ(AspectJは本来syntheticメソッドには関わらない)で、AspectJがsyntheticをサポートすることはない(Java言語には無いので)ってことに。

[aspectj-users] クラスアノテーションとメソッドアノテーションの組み合わせ

[aspectj-users] Combination of Class Annotation and Method Annotation matching

僕の投稿なんですが。

class Base{ void func(){} }

@Annot
class Derived extends Base{
 @Annot void func(){}
}

こんなクラスがある場合、execution(@Annot * (!@Annot *).*(..))というポイントカットが、Derived.funcにマッチするのは何故?って話。

結論としては、AspectJのマッチング仕様としては正しい動作らしい。
AspectJのマッチングは、実際にはメソッドそのものではなくそのシグネチャとマッチングを行っていて、1つのメソッドは複数のシグネチャを持ち、かつアノテーション等のデジネータは上書きされるってことらしい。つまり、Derived.funcは、親クラスのfuncのシグネチャを引き継ぐため、"Base.func"と"@Annot void (@Annot Derived).func"の2つのシグネチャを持つ。で、前述のポイントカットは上書きされて"@Annot Base.func()"になるので、Derived.funcがマッチするそうな。

これをマッチさせないための対処としてはexecution(@Annot * *.*(..)) && !within(@Annot *)というポイントカットを使うこと。

なんか釈然としないので、その後も議論の継続を試みたのだけど、止まってしまった。
クラスアノテーションもオーバーライドされれば(void Derived.funcが@Annot void (@Annot Base).func()と扱われれば)、すっきりすると思うんだけどなぁ。