AOP异常处理

时间:2012-06-08 11:26:32

标签: java exception-handling aop

我看到Guice和Spring使用AOP联盟进行方法拦截,我一直试图弄清楚如何让AOP联盟拦截和处理某些异常,所以我不必继续编写相同的内容。在每个catch块内反复编码。

但是在审查了这个游戏之后,看起来AOP联盟并没有提供任何方法来拦截抛出的Throwable,以便处理程序/拦截器可以执行某些操作(记录异常等)然后确定是否进一步传播异常,或者只是恢复到引发异常的行之后的下一行

HerpDerp hd = null;

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

Manny.pacquiao();

我正在寻找一种AOP异常处理机制,它拦截RuntimeException并使用业务逻辑来决定是继续传播它还是在Manny.pacquioa()调用时恢复。

  • 如果在Java中无法做到这一点,请告诉我
  • 无论是否可以在Java中执行此操作,是否有办法拦截抛出异常与AOP联盟或我必须去其他地方。如果我必须去别的地方,在哪里? AspectJ的?

谢谢!

4 个答案:

答案 0 :(得分:36)

您可以使用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.");
    }
}
}

但无法返回调用方法或继续处理后续行。但是,如果你在这里处理异常,除非你自己重新抛出它,否则它不会起泡链。

答案 1 :(得分:4)

这是不存在的原因。它需要重写代码的块结构,就像你首先编写try / catch块一样。在我看来,这可能会对可变范围和其他事情造成严重破坏。您要求AOP将字节代码重写为类似下面的代码,并且这是相当重写的。

HerpDerp hd = null;

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

Manny.pacquiao();

答案 2 :(得分:2)

要使用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
}

我认为不可能“回到”执行点。

答案 3 :(得分:2)

@ 4herpsand7derpsago如果您要做的是使用AOP捕获抛出的异常来执行各种任务来处理它然后回到最初抛出异常的代码,我想您错过了AOP的概念

正如你在代码中指出的那样

HerpDerp hd = null;

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

Manny.pacquiao();

如果您希望AOP抓住RuntimeException,请执行一些操作来处理它并返回Manny.pacquiao();,答案是您不能。 原因是当AOP抛出并捕获RuntimeException时,堆栈已经在您的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

之前