Joinpoint vs. ProceedingJoinPoint in AspectJ – AspectJ中的Joinpoint vs. ProceedingJoinPoint

最后修改: 2021年 9月 16日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this short tutorial, we’ll learn about the differences between JoinPoint and ProceedingJoinPoint interfaces in AspectJ.

在这个简短的教程中,我们将了解JoinPointProceedingJoinPoint接口之间的区别AspectJ

We’ll cover it with a brief explanation and code examples.

我们将通过简单的解释和代码实例来介绍。

2. JoinPoint

2.连接点

JoinPoint is an AspectJ interface that provides reflective access to the state available at a given join point, like method parameters, return value, or thrown exception. It also provides all static information about the method itself.

JoinPoint是一个AspectJ接口,提供对给定连接点可用状态的反射性访问,如方法参数、返回值或抛出的异常。它还提供了关于方法本身的所有静态信息。

We can use it with the @Before, @After, @AfterThrowing, and @AfterReturning advice. These pointcuts will launch respectively before the method execution, after execution, after returning a value, or only after throwing an exception, or only after the method returns a value.

我们可以将其与@Before@After@AfterThrowing@AfterReturning建议一起使用。这些提示将分别在方法执行前、执行后、返回值后、或仅在抛出异常后、或仅在方法返回值后启动。

For better understanding, let’s take a look at a basic example. First, we’ll need to declare a pointcut. We’ll define as every execution of getArticleList() from ArticleService class:

为了更好地理解,让我们看一下一个基本的例子。首先,我们需要声明一个点切。我们将定义为每次从ArticleService类中执行getArticleList()

@Pointcut("execution(* com.baeldung.ArticleService.getArticleList(..))")
public void articleListPointcut(){ }

Next, we can define the advice. In our example, we’ll use the @Before:

接下来,我们可以定义建议。在我们的例子中,我们将使用@Before

@Before("articleListPointcut()")
public void beforeAdvice(JoinPoint joinPoint) {
    log.info(
      "Method {} executed with {} arguments",
      joinPoint.getStaticPart().getSignature(),
      joinPoint.getArgs()
    );
}

In the above example, we use the @Before advice to log method execution with its parameters. A similar use case would be to log exceptions that occur in our code:

在上面的例子中,我们使用@Before建议来记录方法的执行和其参数。一个类似的用例是记录我们代码中出现的异常。

@AfterThrowing(
  pointcut = "articleListPointcut()",
  throwing = "e"
)
public void logExceptions(JoinPoint jp, Exception e) {
    log.error(e.getMessage(), e);
}

By using the @AfterThrowing advice, we make sure the logging happens only when the exception occurs.

通过使用@AfterThrowing建议,我们确保日志记录只在异常发生时发生。

3. ProceedingJoinPoint

3.ProceedingJoinPoint

ProceedingJoinPoint is an extension of the JoinPoint that exposes the additional proceed() method. When invoked, the code execution jumps to the next advice or to the target method. It gives us the power to control the code flow and decide whether to proceed or not with further invocations.

ProceedingJoinPointJoinPoint的扩展,暴露了额外的proceed()方法。当被调用时,代码执行会跳到下一个建议或目标方法。它给了我们控制代码流的权力并决定是否继续进行进一步的调用。

It can be just with the @Around advice, which surrounds the whole method invocation:

它可以只是用@Around建议,它围绕着整个方法调用。

@Around("articleListPointcut()")
public Object aroundAdvice(ProceedingJoinPoint pjp) {
    Object articles = cache.get(pjp.getArgs());
    if (articles == null) {
        articles = pjp.proceed(pjp.getArgs());
    }
    return articles;
}

In the above example, we illustrate one of the most popular usages of @Around advice. The actual method gets invoked only if the cache doesn’t return a result. It’s the exact way the Spring Cache Annotations work.

在上面的例子中,我们说明了@Around建议的一个最常用的用法。实际的方法只有在缓存没有返回结果时才会被调用。这正是Spring Cache Annotations的工作方式。

We could also use the ProceedingJoinPoint and @Around advice to retry the operation in case of any exception:

我们还可以使用ProceedingJoinPoint@Around建议,在出现任何异常时重试操作。

@Around("articleListPointcut()")
public Object aroundAdvice(ProceedingJoinPoint pjp) {
    try {
        return pjp.proceed(pjp.getArgs());
    } catch (Throwable) {
        log.error(e.getMessage(), e);
        log.info("Retrying operation");
        return pjp.proceed(pjp.getArgs());
    }
}

This solution can be used, for example, to retry HTTP calls in cases of network interruptions.

例如,这一解决方案可用于在网络中断的情况下重试HTTP调用。

4. Conclusion

4.总结

In this article, we’ve learned about the differences between Joinpoint and ProceedingJoinPoint in AspectJ. As always, all the source code is available over on GitHub.

在这篇文章中,我们已经了解了JoinpointProceedingJoinPointAspectJ中的区别。一如既往,所有的源代码都可以在GitHub上找到