1. Обзор
В этом руководстве мы будем использовать AspectJ для записи вывода журнала трассировки при вызове методов настроенных классов. Используя рекомендацию АОП для записи выходных данных журнала трассировки, мы инкапсулируем логику в единую единицу компиляции.
Наш пример расширяет информацию, представленную во Введении в AspectJ .
2. Аннотация ведения журнала трассировки
Мы будем использовать аннотацию для настройки классов, чтобы можно было отслеживать вызовы их методов. Использование аннотации дает нам простой механизм для добавления вывода журнала трассировки в новый код без необходимости добавлять операторы журнала напрямую.
Создадим аннотацию:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Trace {
}
3. Создание нашего аспекта
Мы создадим аспект, чтобы определить наш pointcut
, чтобы он соответствовал интересующим нас точкам соединения и рекомендациям вокруг
, содержащим логику для выполнения.
Наш аспект будет выглядеть примерно так:
public aspect TracingAspect {
private static final Log LOG = LogFactory.getLog(TracingAspect.class);
pointcut traceAnnotatedClasses(): within(@Trace *) && execution(* *(..));
Object around() : traceAnnotatedClasses() {
String signature = thisJoinPoint.getSignature().toShortString();
LOG.trace("Entering " + signature);
try {
return proceed();
} finally {
LOG.trace("Exiting " + signature);
}
}
}
В нашем аспекте мы определяем pointcut
с именем traceAnnotatedClasses
, чтобы соответствовать выполнению
методов в
классах, аннотированных нашей аннотацией Trace .
Определив и назвав pointcut,
мы можем повторно использовать его, как метод в классе. Мы будем использовать этот именованный pointcut
для настройки нашего совета
.
Наш совет вокруг
будет выполняться вместо любой точки соединения, соответствующей нашему pointcut
, и будет возвращать Object
. Имея тип возвращаемого значения Object
, мы можем учитывать рекомендованные методы, имеющие любой тип возвращаемого значения, даже void
.
Мы извлекаем подпись совпадающей точки соединения, чтобы создать короткое строковое
представление подписи, чтобы добавить контекст к нашим сообщениям трассировки. В результате наш вывод журнала будет иметь имя класса и выполненный метод, что дает нам необходимый контекст.
В промежутках между вызовами вывода трассировки мы вызвали метод с именем continue
. Этот метод доступен для рекомендаций вокруг
, чтобы продолжить выполнение совпадающей точки соединения. Тип возвращаемого значения будет Object
, поскольку у нас нет возможности узнать тип возвращаемого значения во время компиляции. Мы отправим это значение обратно вызывающей стороне после отправки окончательного вывода трассировки в журнал.
Мы заключаем вызов continue() в блок
try
/ finally
, чтобы обеспечить запись выходного сообщения. Если бы мы хотели отследить сгенерированное исключение, мы могли бы добавить совет after()
для записи сообщения в журнал при сгенерированном исключении:
after() throwing (Exception e) : traceAnnotatedClasses() {
LOG.trace("Exception thrown from " + thisJoinPoint.getSignature().toShortString(), e);
}
4. Аннотирование нашего кода
Теперь нам нужно включить нашу трассировку. Давайте создадим простой класс и активируем ведение журнала трассировки с нашей пользовательской аннотацией:
@Trace
@Component
public class MyTracedService {
public void performSomeLogic() {
...
}
public void performSomeAdditionalLogic() {
...
}
}
При наличии аннотации Trace
методы в нашем классе будут соответствовать определенному нами pointcut
. При выполнении этих методов сообщения трассировки будут записываться в журнал.
После запуска нашего кода, вызывающего эти методы, наш вывод журнала должен включать содержимое, подобное следующему:
22:37:58.867 [main] TRACE c.b.a.c.TracingAspect - Entering MyTracedService.performSomeAdditionalLogic()
22:37:58.868 [main] INFO c.b.a.c.MyTracedService - Inside performSomeAdditionalLogic...
22:37:58.868 [main] TRACE c.b.a.c.TracingAspect - Exiting MyTracedService.performSomeAdditionalLogic()
22:37:58.869 [main] TRACE c.b.a.c.TracingAspect - Entering MyTracedService.performSomeLogic()
22:37:58.869 [main] INFO c.b.a.c.MyTracedService - Inside performSomeLogic...
22:37:58.869 [main] TRACE c.b.a.c.TracingAspect - Exiting MyTracedService.performSomeLogic()
5. Вывод
В этой статье мы использовали AspectJ для перехвата всех методов класса с помощью одной аннотации к классу. Это позволяет нам быстро добавить нашу функциональность ведения журнала трассировки в новый код.
Мы также объединили нашу логику вывода журнала трассировки в единый модуль компиляции, чтобы улучшить нашу способность изменять вывод журнала трассировки по мере развития нашего приложения.
Как всегда, полный исходный код статьи доступен на GitHub .