JAVA建议注释将运行两次?

Hea*_*ren 3 java aspectj

就我而言,我正在使用以下内容advice

  @Around(value = "@annotation(MyAnnotation)  && args(MyArgs)")
Run Code Online (Sandbox Code Playgroud)

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

  @MyAnnotation(type = MyType.CREATE)
  public void add(MyArgs) { 
  ...
  }
Run Code Online (Sandbox Code Playgroud)

但是在这篇文章中,它说:

可能发生的错误

仅使用注释会产生另一个问题,我们在使用模式时无需考虑;这将使我们的建议运行两次(或多次),因为注释切入点未指定是否应在执行或初始化期间运行它。

据我了解,这似乎是正确的,一旦join point达到并满足条件,建议应该运行(当时我的建议上面会运行两次-在通话exeuction)。我应该使用以下建议来避免这种情况。

  @Around(value = "@annotation(MyAnnotation)  && execution(* *(..)) && args(MyArgs)")
Run Code Online (Sandbox Code Playgroud)

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

这是正确的吗?还是不是advice运行方式?

更新于2018-04-16

@Nandor是正确的,我使用的是Spring AOP而不是AspectJ。我开始了一个演示,清楚地证明了他的观点。谢谢Nandor。

Nán*_*ete 5

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

@annotation(MyAnnotation)
Run Code Online (Sandbox Code Playgroud)

匹配方法执行和方法调用连接点。请参阅AspectJ编程指南中的调用与执行。由于切入点表达式不限于调用执行联接点,因此它将匹配。如果您实际在项目中使用AspectJ,则将同时为您的周围建议提出建议,并且您将面临所提到的帖子中警告过的问题。

使用此切入点表达式不会导致周围的建议执行两次的事实意味着您实际上不使用AspectJ,而使用的是Spring AOP,它仅支持方法执行切入点(请参阅Spring AOP功能和目标)。

Spring AOP当前仅支持方法执行连接点(建议在Spring Bean上执行方法)。

并且仅适用于公共方法,这是因为Spring AOP基于代理的性质(还有许多其他限制)。

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

@annotation(MyAnnotation) && execution(public * *(..))
Run Code Online (Sandbox Code Playgroud)