JAVA请教注解会运行两次?

JAVA advice annotation will run twice?

在我的例子中,我使用以下 advice:

  @Around(value = "@annotation(MyAnnotation)  && args(MyArgs)")

一旦将 MyAnnotation 添加到方法中,它就可以正常工作,并且 MyArgs 也将被检索。

  @MyAnnotation(type = MyType.CREATE)
  public void add(MyArgs) { 
  ...
  }

但是在这个 post 中,它说:

The errors that can and will occur

Using only annotations creates another problem that we don’t need to think about while using patterns; It will make our advice run twice(or more), because the annotation pointcut don’t specify if it should be run during execution or initialization.

据我了解,一旦达到join point并满足条件,建议应该运行(那么我上面的建议将运行 两次 - 调用执行)。我应该使用以下 建议 来避免它。

  @Around(value = "@annotation(MyAnnotation)  && execution(* *(..)) && args(MyArgs)")

但是我调试了我的代码,它只 运行 一次没有添加 execution(* *(..)).

这样对吗?或者这不是 advice 运行 的方式?

2018-04-16 更新

@Nandor 是对的,我使用的是 Spring AOP 而不是 AspectJ。我启动了一个 maven demo 清楚地证明了他的观点。谢谢你,南多尔。

如果您使用的是 AspectJ,您的建议将被触发两次,因为切入点表达式

@annotation(MyAnnotation)

匹配方法 execution 和方法 call 连接点。请参阅 AspectJ 编程指南中的 call vs execution。由于您的切入点表达式不限于 callexecution 连接点,因此它将匹配两者。如果您实际上在您的项目中使用了 AspectJ,那么您的 around 建议将同时被触发,并且您将面临您所指的 post 中被警告的问题。

使用这个切入点表达式不会导致周围建议执行两次的事实意味着您实际上没有使用 AspectJ,而是使用 Spring AOP,它只支持方法执行切入点(参见 Spring AOP capabilities and goals

Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans).

并且仅适用于 public 方法,因为 Spring AOP 的基于代理的性质(除了许多其他限制)。

如果要创建与 Spring AOP 和 AspectJ 行为相同的切入点表达式,请确保始终通过添加相应的切入点表达式将切入点约束为方法执行,例如:

@annotation(MyAnnotation) && execution(public * *(..))