Aspectj"投掷后#34; - 监控特定异常

时间:2018-01-17 08:55:41

标签: java aspectj pointcut

我试图通过aspectj捕获从应用程序代码抛出的所有 MySpecificException 异常。

有很多地方可以抛出此异常。 抛出异常后,我想记录它或进行一些操作(无论是否稍后捕获)。

我尝试过使用:

@AfterThrowing(value = "(execution(* *.*(..))), throwing = "throwable")

但这是矫枉过正,因为它捕获了所有异常。我可以稍后手动过滤,但我试图避免这种情况(由于我的应用程序性质,在某些情况下由于类加载器问题导致加载时间问题)

我也尝试过:

@AfterThrowing(value = "(execution(* *.*(..))) throws MySpecificException, throwing = "throwable")

但它还不够,因为如果该方法声明它会抛出大量异常会怎样?

有关如何仅捕获我的相关异常而不在切入点实现中过滤它们的任何建议?

谢谢

1 个答案:

答案 0 :(得分:1)

您的代码不可执行,请在下次提供MCVE或至少完整的方面。您甚至不提供建议的签名。这不是一个在SO上提问的好方法。作为拥有1,000+声望点的用户,您应该知道这一点。

无论如何,你的问题的答案实际上非常简单。假设你有这个示例代码:

异常类+驱动程序应用程序:

package de.scrum_master.app;

public class MySpecificException extends Exception {
  private static final long serialVersionUID = 1L;
}
package de.scrum_master.app;

import java.io.IOException;

public class Application {
  public String doSomething(Integer number) {
    return number.toString();
  }

  public void doSomethingElse(boolean doThrow) throws MySpecificException {
    if (doThrow)
      throw new MySpecificException();
  }

  public void doWhatever(boolean doThrow) throws MySpecificException, IOException {
    if (doThrow)
      throw new MySpecificException();
    else
      throw new IOException();
  }

  public static void main(String[] args) throws MySpecificException, IOException {
    Application application = new Application();

    // Just so as not to mess up the console output in the IDE for this demo
    System.setErr(System.out);

    // No exceptions here
    application.doSomething(11);
    application.doSomethingElse(false);

    // Let's catch some exceptions
    try {
      application.doSomethingElse(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(false);
    } catch (IOException e) {
      System.out.println("Caught " + e);
    }

    // Do not catch this one
    application.doSomethingElse(true);
  }
}

没有方面的控制台日志:

Caught de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)

这里没有惊喜。我们已经发现了不同类型的例外情况。现在我们希望有一个方面专门记录所有MySpecificException的出现,无论它们是否被捕获。

<强>方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

import de.scrum_master.app.MySpecificException;

@Aspect
public class ExceptionLogger {
  @AfterThrowing(value = "(execution(* *.*(..)))", throwing = "mySpecificException")
  public void logException(JoinPoint thisJoinPoint, MySpecificException mySpecificException) {
    System.out.println(thisJoinPoint + " -> " + mySpecificException);
  }
}

查看建议方法的签名?只需将异常参数限制为所需类型即可。

带方面的控制台日志:

execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.doWhatever(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.main(String[])) -> de.scrum_master.app.MySpecificException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)