4

In my case, I am using the following advice:

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

and it works fine once the MyAnnotation is added to the method and MyArgs will also retrieved.

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

But in this post, it says:

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.

To my understanding, it seems right once the join point reached and the condition is met, the advice should run (then my advice above will run twice - the call and the exeuction). And I should use the following advice to avoid it.

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

But I debugged my code, it only runs once without adding execution(* *(..)).

Is this right? Or it's not the way in which advice runs?

Updated 2018-04-16

@Nandor is right, I was using Spring AOP instead of AspectJ. I started a maven demo clearly demonstating his point. Thank you, Nandor.

Community
  • 1
  • 1
Hearen
  • 7,420
  • 4
  • 53
  • 63
  • Does it also run once without adding `args(MyArgs)`? – smac89 Apr 12 '18 at 01:33
  • @smac89 It's about the timing aspect instead of `args`, which is used to retrieve the `args` to filter out other methods using the same `MyAnnotation`. – Hearen Apr 12 '18 at 01:38
  • Are you using Spring AOP? – Nándor Előd Fekete Apr 12 '18 at 21:58
  • @Naidor Actually I'm using AspectJ, you can check [Spring AOP capabilities and goals](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-introduction-spring-defn) for reference. – Hearen Apr 13 '18 at 01:04
  • 1
    @Hearen I don't need to check out Spring AOP as I know it quite well, as well as AspectJ. I asked that question because your answer below is wrong, and I suspected that's because you got confused by the usual Spring AOP vs AspectJ conflation. Do you have compile time weaving set up in your build? Or do you have load time weaving enabled in your runtime? – Nándor Előd Fekete Apr 13 '18 at 02:20
  • @Naidor I do not understand why you are talking about `compile` and `load` time weaving. Is there anything related to this aspect? Will these two differences affect the `run twice` issue? Could you please share some details about it? Or some doc I can find out the details myself? Thank you, Nandor. – Hearen Apr 13 '18 at 13:47
  • @Nandor I checked a [post](https://stackoverflow.com/questions/13781372/java-aspect-oriented-programming-runtime-aspect-weaving-and-class-loading-time) about the `compile` and `load` time weaving. But I do not think there is anything to do with the `run twice` issue. Please do enlighten me and provide some details. Thank you – Hearen Apr 13 '18 at 14:10
  • @Nandor Also I checked its official [doc](https://www.eclipse.org/aspectj/doc/released/devguide/ltw.html#ltw-introduction), I still have no idea what relationship it could be with the `run twice` issue. Nandor, please share some details. Thank you so much. – Hearen Apr 13 '18 at 14:20
  • @Hearen I was asking that question about whether you have compile time weaving or load time weaving, because, if your answer to both is __no__, that means you're __not__ using AspectJ. – Nándor Előd Fekete Apr 14 '18 at 13:59

1 Answers1

6

If you were using AspectJ, your advice would be triggered twice, because the pointcut expression

@annotation(MyAnnotation)

matches both method execution and method call join points. See call vs execution in the AspectJ programming guide. Since your pointcut expression is not restricted to either call or execution join points, it will match both. If you were actually using AspectJ in your project, your around advice would be triggered for both and you would face the issue you were warned about in the post you are referring to.

The fact that using this pointcut expression doesn't result in the around advice executing twice means that you are in fact not using AspectJ and you're using Spring AOP instead, which only supports method execution pointcuts (see Spring AOP capabilities and goals)

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

and only for public methods, because of the proxy based nature of Spring AOP (besides many other limitations).

If you want to create pointcut expressions that would behave the same with both Spring AOP and AspectJ, make sure to always constrain the pointcut to method execution by adding the corresponding pointcut expression, for example:

@annotation(MyAnnotation) && execution(public * *(..))
Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47