javaaopaspectjpointcutspointcut

@AspectJ pointcut for methods that override an interface method with an annotation


How can I write an aspectj pointcut that applies to method executions which override an interface method with an annotation? For example:

interface A {
  @MyAnnotation void method();
}
class B implements A {
  void method();
}

The pointcut execution(@MyAnnotation * *.*(..)) does only match if B.method() carries the annotation itself. Is there another way to do this?


Solution

  • As Nicholas pointed out, this is not possible in AspectJ. Here is more proof of why it is not possible (taken from http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html section Annotation Inheritance and pointcut matching):

    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. The call to c2.aMethod (that would be b.method() in your example) is not matched because join point matching for modifiers (the visibility modifiers, annotations, and throws clause) is based on the subject of the join point (the method actually being called).

    Having suffered from this same issue, I have written a small method/library that would allow you to write pointcuts for such methods. Here is how it would work for your example:

    myAnnotationIsExecuted(): execution(public * *.*(..)) && 
                 if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));
    

    OR

    myAnnotationIsExecuted(): execution(public * A+.*(..)) &&
                 if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));
    

    The method implementsAnnotation(String,JoinPoint) is coming from the library; a basic method that checks if the implemented methods contain the specified annotation.

    More information about the method/library can be found here.