1

Thanks for all the friends here. I know how to get the annotation parameter for the annotation set on method.

While I would like to add the annotation in the Class level. How to retrieve the attribute from Class in the AOP Around method?

By the way, I have another question, why I need to change the response value from void to Object and return pjp.proceed(). If the method do not have response, the request will freezing.

For the Method which has HasRole annotation

@Around("@annotation(com.example.demo.aspect.annotation.HasRole) && @annotation(annotation)")
public void aroundHasRole(ProceedingJoinPoint pjp, HasRole annotation) throws Throwable {

    log.info("value->>{}", annotation.value());
    pjp.proceed();

}

For Class or Method which has HasRole annotation

@Around("(@within(com.example.demo.aspect.annotation.IsAdmin)"
        + "|| @annotation(com.example.demo.aspect.annotation.IsAdmin))")
public Object aroundHasRole(ProceedingJoinPoint pjp) throws Throwable {

    <<How to get annotation information here?>>
    return pjp.proceed();

}

tony
  • 91
  • 1
  • 8
  • Your question is unclear and as you say, you ask *two* questions. Please clarify and focus on what exactly you're looking for. – Giorgi Tsiklauri Aug 23 '20 at 16:43
  • Sorry about that. But the question is in the same `method`. I think they all are related. So I ask them in the same post. – tony Aug 25 '20 at 13:42
  • But no matter what, thank for your reminder. @GiorgiTsiklauri – tony Aug 25 '20 at 13:44

2 Answers2

2

As you probably have noticed, you cannot bind information from different || branches to an advice method parameter because it would be ambiguous, see also my answers here and here. So if you want to avoid ugly (and slow) reflection, do what I recommended in the other answers and write two distinct advices, factoring out the common code into a helper method if avoiding code duplication is your concern here. Something like this (untested, just to give you an idea about the code structure):

@Around("@within(annotation)")
public Object classIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

@Around("@annotation(annotation)")
public Object methodIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

public Object commonIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  // Here you would place all common advice code.
  // Non-common code could remain in the original advice methods.
  log.info("value->>{}", annotation.value());
  return pjp.proceed();
}

why I need to change the response value from void to Object and return pjp.proceed(). If the method do not have response, the request will freezing.

In contrast to a @Before or @After advice, in an @Around advice you can modify the return value by either skipping the target method execution completely by not calling proceed() or by discarding or modifying the result of proceed(). You are completely free in what you want to return, it just has to match the target method's return type.

Having said that, it should become clear that an around advice method also must have a return type matching that of the target method(s) it intercepts. It can be an exact type like MyType, a super type or simply Object (super type for all types) if your advice targets a multitude of types without a common super type. The advice can also have a return type of void if (and only if) all target methods also return void (otherwise the advice just would not match those methods, even if the pointcut as such would match).

So if an around advice matches is determined by a combination of the pointcut itself and the return type. You can use that as a tool to limit pointcut matching by defining a specific return type (to which you then would need to cast the return value of proceed() because proceed() always returns an Object).

BTW, if the target method returns a primitive type like int, boolean etc., then the advice would auto-wrap the result to be an Integer or Boolean.

You really ought to read Spring AOP and AspectJ manuals or tutorials because I am explaining things here which can be found there.


Update: The OP asked for documentation concerning parameter binding and a description how names are determined:

  • You can specify an argNames parameter for all advice types, e.g. @Before, @After, @Around.
  • If that annotation parameter is absent, Spring AOP will try to match advice method parameter names via class file debug info, if compiled in. Otherwise matching would fail in this case.
  • When using full AspectJ with compile-time weaving instead of Spring AOP, determining names also works without debug info because the AspectJ compiler can determine the necessary information during compilation.

All of this is described in the Spring AOP manual.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • OP has a question about the return from Around advice. The answer would be complete if you can cover that as well – R.G Aug 24 '20 at 01:16
  • Thanks for the help! Are there any manual shows when the parameter name in the advice same as the method parameter will be auto binding? I only found it from the forum. – tony Aug 24 '20 at 15:30
  • What do you mean by "auto binding"? Please give an example or just link to where you found what you are asking about. – kriegaex Aug 25 '20 at 00:56
  • I mean ""auto binding" is If the variable "nameBinding" in `@Around("@annotation(nameBinding)") ` is same as the parameter in the method `public Object methodIsAdmin(ProceedingJoinPoint pjp, IsAdmin nameBinding) throws Throwable {`. We can get the variable. – tony Aug 25 '20 at 13:32
  • How does it work? I have no idea. I did not find any document to describe it. – tony Aug 25 '20 at 13:35
  • 1
    I updated my answer in order to briefly explain advice parameter matching and add a documentation link for your convenience. – kriegaex Aug 25 '20 at 13:46
0

Obtain the class through reflection, obtain the fixed method information through the class, and get the annotation on the method. In this way, you should be able to reflect

jml940616
  • 11
  • 1