0

The idea is to create annotations hierarchy (similar to @Service, @Component etc) using @AliasFor annotation. This should give me the possibility to define aspect, that would execute on parent annotation, and every alias of it. But somehow it doesn't work for me.

@ComponentScan is fine, @EnableAspectJAutoProxy is set.

Example:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ParentAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ParentAnnotation
public @interface ChildAnnotation {

    @AliasFor(annotation = ParentAnnotation.class)
    String value() default "";
}
@Aspect
@Component
public class EventRecorderAspect {

    @Around("@annotation(com.example.ParentAnnotation)")
    public void exampleMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // This should be executed for both @ParentAnnotation and @ChildAnnotation
    }
}
@RestController
public class ExampleController {
    @ChildAnnotation // This should result in executing aspect for every implementation
    String controllerMethod(); 
}

UPDATE: I've updated code, as @M.Deinum suggested in a comment below. But it still doesnt work.

Ariel Grabijas
  • 1,472
  • 5
  • 25
  • 45
  • The `ChildAnnotation` isn't marked with `@ParentAnnotation` so how should that work? – M. Deinum Dec 01 '21 at 10:58
  • Geez, I missed that. Thanks! – Ariel Grabijas Dec 01 '21 at 11:01
  • OK, after refactor it still doesn't work. Aspect triggers for parent annotation, but not for child. – Ariel Grabijas Dec 01 '21 at 12:26
  • 1
    It needs to be `@Inherited` as well afaik and Spring itself has dedicated support for composed annotations, so not sure if that would work with a regular Aspectj. – M. Deinum Dec 01 '21 at 12:31
  • @M.Deinum, `@Inherited` only applies to annotations on classes inherited by other classes, neither to annotations on interfaces or to meta annotations, nor to annotations on methods or other elements. – kriegaex Dec 09 '21 at 00:47
  • @kriegaex So is there a way to somehow inherit annotations from interface method to class method? I'm speaking about example wher `ExampleController` implements interface, which containts method annotated with `@ChildAnnotation` and O would like to execute this aspect for any method from any inerface, that is annotated as `@ChildAnnotation` – Ariel Grabijas Dec 09 '21 at 16:57
  • I updated my answer in order to answer your question. – kriegaex Dec 10 '21 at 02:22

1 Answers1

1

AspectJ pointcut matching syntax, a subset of which is used by Spring AOP, is ignorant of meta annotations, even though withing the Spring framework as such there is support for it in other places. I think the closest you can get to specifying meta annotations in your pointcut is to do it explicitly up to the nesting level you require. See this answer for examples showing the syntax variants for both

  • class-level, e.g. within(@(@com.example.ParentAnnotation *) *),
  • method-level, e.g. execution(@(@com.example.ParentAnnotation *) * *(..))

annotations.


Update: @Ariel Grabijas asked in a follow-up comment:

So is there a way to somehow inherit annotations from interface method to class method?

Not in Java and also not by means of Spring AOP. But there is a workaround using native AspectJ inter-type definitions (ITD).

kriegaex
  • 63,017
  • 15
  • 111
  • 202