Skip to content

Discover annotations on interface methods for AspectJ annotation pointcuts #22311

Open
@cdfive

Description

@cdfive

Affects: spring-aop:5.0.9.RELEASE, spring-boot-starter-aop:2.0.5.RELEASE

public interface FooService {

  @MyAnnotation 
  void hello();
}

public class FooServiceImpl implements FooService {

  void hello();
}
public class MyAspect {

  @Pointcut("@annotation(MyAnnotation")
     public void myPointcut() {
   }

  @Around("myPointcut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable {
     ...
  }
}
@Configuration
public class MyAopConfiguration {
    @Bean
    public MyAspect myAspect () {
        return new MyAspect();
    }
}

Using spring-aop like the code above, it doesn't work, around(ProceedingJoinPoint pjp) never executes.

If put the @MyAnnotation on the implemented method of FooServiceImpl, it works.

public interface FooService { 

  void hello();
}

public class FooServiceImpl  implements FooService {

  @MyAnnotation
  void hello();
}

Learned from two questions in Stack Overflow:

According to the Java 5 specification, non-type annotations are not inherited, and annotations on types are only inherited if they have the @Inherited meta-annotation.

It's seems that it's impossible in spring-aop.

I tried the code without spring-aop, only using aspectjweaver 1.7.4, and adding an aop.xml in resources/META-INF:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
    <aspects>
        <aspect name="com.xxx.MyAspect"/>
    </aspects>
    <weaver options="-verbose -showWeaveInfo -Xset:weaveJavaxPackages=true" />
</aspectj>

and adding JVM parameter:

-javaagent:xxx/aspectjweaver-1.7.4.jar

It works no matter the @MyAnnotation is on the interface or class. And then in around(ProceedingJoinPoint pjp), I can get the @MyAnnotation with the API of pjp, like this:

MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Class<?> targetClass = pjp.getTarget().getClass();
Method method = targetClass.getDeclaredMethod(signature.getName(), signature.getMethod().getParameterTypes());
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

or

Class<?>[] interfaces = targetClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
   Method method = targetClass.getDeclaredMethod(signature.getName(), 
   signature.getMethod().getParameterTypes());
   MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
}

So I think spring-aop may also have way to solve this problem, since it's a common use case for users to add annotation on the method of interface.

Something in AopUtils#getMostSpecificMethod, AspectJExpressionPointcut#getShadowMatch(Method targetMethod, Method originalMethod) may be about, I'm not sure.

Could you please give some help?

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions