Contents

使用 AspectJ 为带注释的类提供建议方法

1. 概述

在本教程中,我们将在调用配置类的方法时使用AspectJ编写跟踪日志输出。 通过使用 AOP 建议来编写跟踪日志输出,我们将逻辑封装到单个编译单元中。

我们的示例扩展了Intro to AspectJ 中提供的信息。

2. 跟踪日志注解

**我们将使用注释来配置类,以便可以跟踪它们的方法调用。**使用注释为我们提供了一种简单的机制,可以将跟踪日志输出添加到新代码中,而无需直接添加日志语句。

让我们创建注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Trace {
}

3. 创造我们的切面

*我们将创建一个切面来定义我们的pointcut,以匹配我们关心的连接点和包含要执行的逻辑的*around advice

我们的方面看起来与此类似:

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

在我们的方面,我们定义了一个名为traceAnnotatedClassespointcut ,以匹配使用Trace注释的类中within方法的execution 。**通过定义和命名pointcut,我们可以像在类中的方法一样重用它。**我们将使用这个命名的pointcutaround advice配置我们的切入点。

**我们的around advice将代替与我们的pointcut匹配的任何连接点执行,并将返回一个Object。**通过拥有 Object返回类型,我们可以解释具有任何返回类型的建议方法,甚至是void

我们检索匹配连接点的签名以创建签名的短String表示,以将上下文添加到我们的跟踪消息中。结果,我们的日志输出将包含类的名称和执行的方法,这为我们提供了一些所需的上下文。

在我们的跟踪输出调用之间,我们调用了一个名为proceed的方法。此方法可用于around advice,以便继续执行匹配的连接点。**返回类型将是Object,因为我们无法在编译时知道返回类型。我们将在将最终跟踪输出发送到日志后将此值发送回调用方。

**我们将proceed()调用包装在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()