Aspectj(带弹簧) - 在没有传播方法的抛出方法上仅记录一次异常抛出



我们刚刚为所有服务方法实现了日志记录方面。我们还实现了异常抛出日志记录。

问题是如果我们有以下情况:

ClassA.method1 调用 ClassB.method2 调用 ClassC.method3和方法3引发异常。

现在发生的事情是 - 我们记录了方法3和方法2和方法1中抛出的异常。(excpetion被传播,因此从每个中重新抛出)

我们如何实现我的方面将仅处理抛出异常的最后一个方法(method3)?

谢谢!

类似的解决方案在AspectJ in Action中描述。可以实现很多事情,例如方法名称,参数等的日志记录,但为了简单起见:

public aspect ExceptionAspect {
    private Log log = Logger.getLogger("error_log");
    private Exception exception;
    pointcut exceptionPointcut() : execution(* my.package..*(..));
    after() throwing(Exception ex) : exceptionPointcut() {
        if (exception != ex) {
            exception = ex;
            log.error("ERROR: {}", ex);
        }
    }
}

一种解决方案可能是将可抛出对象的引用存储在处理程序类中,其中记录了截获方法。可以WeakSet保存这些引用的良好数据结构,如下所示:

Set<Throwable> throwableRecord = Collections.newSetFromMap(new WeakHashMap<>());

在发生异常的情况下,处理程序首先检查异常是否存在于集合中。否则,可抛出对象将添加到集合中并记录。如果存在,只需忽略该异常,因为它是传播的异常,并且我们确定我们之前记录了它。

if (throwableRecord.contains(throwable)) {
    //dont't log
    //the exception is logged before
}
throwableRecord.add(throwable);
//log the exception

使用 WeakSet 的好处是,每当可抛出对象被 gc 斩封时,其相关条目都会自动从集合中删除。

最新更新