我们刚刚为所有服务方法实现了日志记录方面。我们还实现了异常抛出日志记录。
问题是如果我们有以下情况:
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 斩封时,其相关条目都会自动从集合中删除。