Aspectj "after throwing" - 监控特定异常

Aspectj "after throwing" - monitor a specific exception

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

有很多地方可以抛出这个异常。 一旦抛出异常我想记录它或做一些操作(不管它是否被捕获)。

我试过使用:

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

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

我也试过:

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

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

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

谢谢

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

不管怎样,你的问题的答案其实很简单。假设您有此示例代码:

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

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)