web-dev-qa-db-ja.com

AOP例外処理

GuiceとSpringがメソッドインターセプトのフードの下でAOP Allianceを使用していることを確認し、AOP Allianceが特定の例外をインターセプトして処理する方法を理解しようとしているため、同じコードを何度も書き続ける必要はありません。すべてのcatchブロック内で繰り返します。

しかし、プレイを確認した後、AOPアライアンスは、スローされたThrowablesをインターセプトして、ハンドラー/インターセプターがいくつかのこと(例外のログなど)を実行できるようにして、- 例外をさらに伝播するかどうか、または例外をスローした行の次の行に回復するかどうかを決定します

_HerpDerp hd = null;

if(hd == null)
    throw new RuntimeException("Herpyl derp!");

Manny.pacquiao();
_

RuntimeExceptionをインターセプトし、ビジネスロジックを使用して伝播を続けるか、Manny.pacquioa()呼び出しで回復するかを決定するAOP例外処理メカニズムを探しています。

  • Javaでこれを実行できない場合は、お知らせください。
  • Javaでこれを実行できるかどうかに関係なく、スローされた例外をAOPアライアンスでインターセプトする方法はありますか、それとも別の場所に移動する必要がありますか?そして、どこかに行かなければならない場合、どこに? AspectJ?

ありがとう!

20
IAmYourFaja

Spring AOPで例外をキャッチできますが、それが純粋なJavaフレームワークの要件に一致するかどうかはわかりません。

Springでは、次のような単純なAOPインターセプターを作成できます。

@Aspect
public class ErrorInterceptor{
@AfterThrowing(pointcut = "execution(* com.mycompany.package..* (..))", throwing = "ex")
public void errorInterceptor(WidgetException ex) {
    if (logger.isDebugEnabled()) {
        logger.debug("Error Message Interceptor started");
    }

    // DO SOMETHING HERE WITH EX
    logger.debug( ex.getCause().getMessage());


    if (logger.isDebugEnabled()) {
        logger.debug("Error Message Interceptor finished.");
    }
}
}

ただし、呼び出し元のメソッドに戻ったり、次の行で処理を続行したりする方法はありません。ただし、ここで例外を処理する場合、自分で再スローしない限り、チェーンが浮上することはありません。

35
Eric B.

これが存在しない理由があります。そもそもtry/catchブロックを書いたかのように、コードのブロック構造を書き直す必要があります。これは、私には、変数のスコープやその他のもので潜在的に大混乱を演じているようです。あなたはバイトコードを次のコードのようなものに書き換えるようにAOPに求めています、そしてそれはかなりの書き換えです。

HerpDerp hd = null;

try {
    if(hd == null)
        throw new RuntimeException("Herpyl derp!");
} catch(RuntimeException e) {
   if (someConditionIsMet) {
       throw e;
   }
}

Manny.pacquiao();
4
bmargulies

@ 4herpsand7derpsagoあなたがしようとしているのが、AOPを使用してスローされた例外をキャッチし、それを処理するためのさまざまなタスクを実行してから、例外が最初にスローされたコードに戻ってくる場合、AOPの概念を理解していないと思います。

コードで指摘するように

_HerpDerp hd = null;

if(hd == null)
throw new RuntimeException("Herpyl derp!");

Manny.pacquiao();
_

AOPがRuntimeExceptionをキャッチし、それを処理するためにいくつかの処理を実行してManny.pacquiao();に戻ってくる場合、答えはできないです。その理由は、RuntimeExceptionがAOPによってスローおよびキャッチされたとき、スタックはすでにAOPコードにあるためです。 Many.pacquiao();を実行するために戻ることはできません。 Many.pacquiao();の実行を継続する場合の唯一の方法は、次のように_try-finally_ブロックを使用することです

_HerpDerp hd = null;

try {
    if(hd == null)
        throw new RuntimeException("Herpyl derp!");
} finally {
    Manny.pacquiao();
}
_

そうして初めてMany.pacquiao()が実行されますが、AOPがRuntimeExceptionをキャッチする前に

2
Wins

AspectJでキャッチされない例外を「キャッチ」するには、次のアスペクトを使用できます。

pointcut uncaughtExceptionScope() : 
    (execution(* com.mycompany.myrootpackage..Main.main(..)) 
    || execution(* Java.util.concurrent.Callable+.call()) 
    || execution(* Java.lang.Runnable+.run()) 
    ));

after() throwing(Throwable t) : uncaughtExceptionScope() && !cflow(adviceexecution())    {
    handleException(thisJoinPoint, t);
}   

protected void handleException(JoinPoint jp, Throwable t)
{
    // handle exception here
}

実行ポイントに「戻る」ことはできないと思います。

2
Wim Deblauwe