繁体   English   中英

Aspectj(带 spring)- 在没有传播方法的情况下,仅在抛出方法上记录异常抛出一次

[英]Aspectj (with spring) - logging throw of an exception only once on the throwing method without the propagated methods

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

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

ClassA.method1 调用ClassB.method2 调用ClassC.method3,method3 抛出异常。

现在发生的事情是——我们得到了在 method3 AND method2 AND method1 中抛出异常的记录。 (传播并因此从每个中重新抛出)

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

谢谢!

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);
        }
    }
}

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

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

在发生异常的情况下,首先,处理程序检查集合中是否存在异常。 如果不是,则将可抛出的 object 添加到集合中并记录下来。 如果它存在,则简单地忽略该异常,因为它是一个传播的异常,我们确信我们之前记录过它。

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

使用WeakSet的好处是,每当 throwable object 被 gc 垃圾处理时,它的相关条目会自动从集合中删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM