web-dev-qa-db-ja.com

注釈付きメソッドまたは注釈付きクラスのメソッドのポイントカット

私は欲しい @Xアノテーションが付けられたクラスのメソッドまたは@Xアノテーションが付けられたメソッドのポイントカット。私も 注釈オブジェクトが必要。クラスとメソッドの両方に注釈が付けられている場合 メソッドアノテーションを引数として取得することを好みます

次のことを試しましたが、「バインディングに一貫性がありません」という警告が表示されます。 (なぜそれらをnullに設定しないのですか?)

@Around("@annotation(methodLevelX) || @within(classLevelX)")
public Object advise(ProceedingJoinPoint pjp, X methodLevelX, X classLevelX)

以下は、「パラメータxのあいまいなバインディング '||'を作成します。ポイントカットで」警告。 (私の意見では必ずしも意味がありません:最初の短絡評価を拘束しないのはなぜですか?)

@Around("@annotation(x) || @within(x)")
public Object advise(ProceedingJoinPoint pjp, X x)

前の試行を2つに分割すると、クラスとメソッドのアノテーションが存在する場合、当然2つのメソッド呼び出しが発生します。

リフレクションを使用してメソッドとクラスを取得し、次のようなポイントカットを使用して目的のアノテーションを取得できることはわかっています。

@Around("@annotation(com.package.X) || @within(com.package.X)")

しかし、私はしたくないです。

「1つのポイントカット、1つのメソッド、1つのアノテーション引数」、リフレクションを必要としない私の要件の解決策はありますか?

15
Traubenfuchs

完全ではありませんが、ほとんどです。 2つのポイントカットと2つのアドバイスが必要になりますが、作業を1つのメソッドに委任することができます。外観は次のとおりです。

_@Aspect
public class AnyAspectName {

    @Pointcut("execution(@X * *.*(..))")
    void annotatedMethod() {}

    @Pointcut("execution(* (@X *).*(..))")
    void methodOfAnnotatedClass() {}

    @Around("annotatedMethod() && @annotation(methodLevelX)")
    public Object adviseAnnotatedMethods(ProceedingJoinPoint pjp, X methodLevelX) 
            throws Throwable {
        return aroundImplementation(pjp, methodLevelX);
    }

    @Around("methodOfAnnotatedClass() && !annotatedMethod() && @within(classLevelX)")
    public Object adviseMethodsOfAnnotatedClass(ProceedingJoinPoint pjp, X classLevelX) 
            throws Throwable {
        return aroundImplementation(pjp, classLevelX);
    }

    public Object aroundImplementation(ProceedingJoinPoint pjp, X annotation) 
            throws Throwable {
        return pjp.proceed();
    }

}
_

@annotation()@within()のポイントカットを分割することに加えて、結果のポイントカットが広すぎないように制限を追加したことに注意してください。 メソッド実行ジョインポイントが必要だと思うので、メソッド実行に制限する必要なポイントカット式を追加しました。それらは一致しています

  1. _@X_で注釈が付けられたメソッドの実行、最初のアドバイスのための任意のパッケージ内の任意のクラスの任意の戻り値の型
  2. 2番目に_@X_で注釈が付けられた任意のクラスの任意の戻り値の型を持つ任意のメソッドの実行。

@within(X)@annotation(X)をさらに制限すると、@within(X)自体が一致するため便利です。

関連付けられたコードがタイプXのアノテーションを持つタイプで定義されている任意のジョインポイント

これには、method-executionmethod-callconstructor-executionが含まれます。 、コンストラクター呼び出し初期化前静的初期化initializationfield setfield getexception -ハンドラーロックタイプのジョインポイント(ただし、すべてのジョインポイントがアラウンドアドバイスに有効であるとは限りません)。同様に、@annotation(X)自体は

サブジェクトにタイプXの注釈がある任意のジョインポイント

これは、アノテーションのターゲットタイプによっては、前述のほとんどのジョインポイントを意味する場合もあります。

19