abstract pointcutとweavingのスイッチ

GAE/Jで永続化層にJDOを使ってきたのですが、GAE/Jを良く知る為にLow Level APIも試してみたい。そこで、AspectJを使って永続化層をうまく切り替えられないものかな、と。ある永続化層を選択した場合のみweavingされるようなadviceを定義できれば、例えばJavaBeanに対する値の取得/設定を、裏でコッソリEntityのget/putに変換してしまうとか。
取りあえずpointcutとadviceを定義し、実行コンテキストによってadviceの内容を実行するかどうか動的に判断するようにweavingすることは簡単です。例えば先ほどのJavaBean(JDOのデータクラス)→Entityの例で言うと、JavaBeanのsetter/getterをpointcutとし、adviceでは実行コンテキストを見て、Low Level APIであればEntityに処理を委譲する、それ以外はスルーする、というやり方ができると思います。
しかし、委譲するかどうか判定するコードは、実行コンテキストが何であれweavingされてしまうことになります。それがちょっと気持ち悪い。考えを進めていくうちに、adviceをweavingするかどうかを、staticにちょっとした操作で切り替えることができないか、と思うようになりました。
その一つの方法がabstract pointcutです。abstract pointcutは、その名のカンジのとおり、pointcutの具体的な位置を定義しません。しかし、abstract pointcutを指定してadviceを定義することができます。

  abstract pointcut metadtaCollect();
  
  after() : metadtaCollect(){
    InitializerSignature initsig =
      (InitializerSignature)thisJoinPoint.getSignature();
    collectMetadata(initsig.getDeclaringType());
  }

上記コードはadviceの実装がinitializer系のpointcutを前提としてしまっているのであまり良い例ではありませんが、abstract pointcutに対してadviceを定義することができる点が重要です。abstract pointcutに対してadviceが定義されてもweavingされません(どこにweavingするか定義してないので当然ですが)。abstract pointcutを持つaspectは、abstract aspectになります。abstract aspectを継承して、abstract pointcutと同じシグネチャのpointcutを定義することにより、abstract aspectで定義したadvice(上記コードだとcollectMetadataメソッドを呼び出しているブロック)がweavingされます。

public aspect GaeModelMetadataCollectorAtClassInit extends GaeModelMetadataCollector{
	pointcut metadtaCollect() : staticinitialization(net.wrap_trap.bitro.model.Model+);
}

このような仕組みを使うことにより、例えば永続化層の各バリエーションに対してabstract aspectを用意し、使用する永続化層が決まったらそれに対応するabstract aspectを継承したaspect、pointcutを定義することで、必要な実装だけをweavingできます。