Aspectj (с пружиной) - регистрация выброса исключения только один раз в методе throwing без распространяемых методов
Мы только что реализовали аспект ведения журнала для всех наших методов обслуживания. Мы также реализовали ведение журнала исключений.
Проблема в том, что у нас есть следующий сценарий:
ClassA.method1 вызывает ClassB.method2 вызывает ClassC.method3, а method3 создает исключение.
То, что происходит сейчас, - мы получили запись исключения, генерируемого в method3 AND method2 AND method1. (исключение распространяется и поэтому отбрасывается от каждого)
Как мы можем добиться того, чтобы мой аспект обрабатывал только последний метод, выдавший исключение (method3)?
Спасибо!
2 ответа
Решение может состоять в том, чтобы сохранить ссылку на бросаемый объект в классе обработчика, в котором будут зарегистрированы методы перехвата. Хорошая структура данных для хранения этих ссылок может выглядеть примерно так:
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
Преимущество использования
Подобное решение было описано в AspectJ в действии. Есть много вещей, которые могут быть реализованы, такие как регистрация имени метода, аргументов и т. Д., Но для простоты:
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);
}
}
}