0

私はクラスを持っています:

class MyClass {
    @MyAnnotation
    public void someMethod() {

    }
}

ポイントカットのアドバイスでは、基本的にアノテーションの対象となる「メソッド」を抽出しています。次に、いくつかの構成に応じて、メソッドは多くのハンドラーの 1 つに委任されます。

ここで指摘しなければならないのは、すべての問題の原因はjoinPoint.proceed()、アドバイスを実際に実行できないことにあるということです。Method.invoke()並列スレッドでそのメソッドを呼び出し続ける別のデリゲートがあり、その実行にはProceedingJoinPoint.

問題は、Method.invoke()onを実行するたびにsomeMethod、(もちろん) アドバイスが再度実行されることです。これは、注釈が付けられているためです。これにより、何度も何度も実行されます。

次のいずれかに行く必要があります。

  1. リフレクションまたは Method.invoke によって呼び出された場合は、アドバイスを実行しないでください (実際には可能だとは思いません)。
  2. 呼び出しがデリゲートの 1 つからのものであるかどうかを、アドバイス内で検出します。

#2 については、フラグか何かを設定することを検討しましたが、それではもはやスレッドセーフではありません。

助言がありますか?

より明確なコード例:

私は定義されたアスペクトを持っています:

@Pointcut("execution(@com.rohanprabhu.annotation.Process * *(..)) "
        + "&& @annotation(process)")
public void processPointcut(Process process) {
}

@Around("processPointcut(process)")
public Object process(final ProceedingJoinPoint joinPoint, final Process process)
        throws Throwable {
    final Object callingObject = joinPoint.getThis();
    final Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
    final MethodContext methodContext = new MethodContext(callingObject, method);

    //The below mentioned delegate will be picked
    //depending on some validation performed on 'callingObject'
    Object retValue = delegate.process(methodContext, joinPoint.getArgs());
    return retValue;
}

デリゲートは次のようになります。

class SimpleDelegate extends Delegate {
    @Override
    public Object process(final MethodContext methodContext, final Object[] args) {
        // The problem is that following invoke call calls
        // the @Around aspect to run again, which calls the delegate again,
        // which causes execution of the next line, which causes the aspect to run
        // again and so on...
        methodContext.getMethod().invoke(
            methodContext.getCallingObject(),
            args
        );
    }
}

次のようなことができれば素晴らしいと思います(次のようなものがあるとは本当に思いませんcalledByReflection

@Pointcut("execution(@com.rohanprabhu.annotation.Process * *(..)) "
        + "&& @annotation(process)" + " && !calledByReflection")
public void processPointcut(Process process) {
}

または次のようなもの:

@Around("processPointcut(process)")
public Object process(final ProceedingJoinPoint joinPoint, final Process process,
               final boolean processAnnotation)
        throws Throwable {
    if(processAnnotation) {
        // Do the regular stuff
    }
}

processAnnotationそして、アスペクトに価値を提供する方法がいくつかありました。これで私の質問が明確になったことを願っています。}

4

0 に答える 0