Search code examples
javaspring-bootannotationsaopaspect

Aspect to use on methods in classes that has annotation that is inside another annotation


I have service classes that extends BaseService class that has @Annotation1 annotation. In @Annotation1 there is another annotation - @Annotation2.

I want to be able to create aspect method, that runs before all methods in classes annotated with @Annotation2 so in any service that extends BaseService class.

When i apply @Annotation2 directly in BaseService i am able to run aspect method or when i apply @Annotation1 directly on service, but not when @Annotation2 is inside @Annotation1 in extended class

@Annotation1
abstract class BaseService {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Annotation2
public @interface Annotation1 {
}
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Annotation2 {
}
public class TestService extends BaseService {

    private void testMethod(){
        // does some service task
    }
}
@Aspect
public class TestAspect {

    @Before("@within(com.example.Annotation2) ||" +
            " within(@(@com.example.Annotation2 *)*)" +
            " @annotation(com.example.Annotation2)")
    public void aspectMethod(JoinPoint joinPoint) {
        // should run before testMethod 
    }
}

Aspect method aspectMethod() should run before testMethod() in TestService but does not.


Solution

  • According to my other answer I would have expected an aspect like this to work:

    package de.scrum_master.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class TestAspect {
      @Before(
        "execution(* *(..)) && (" +
          "within(@de.scrum_master.app.Annotation2 *) || " +
          "within(@(@de.scrum_master.app.Annotation2 *) *) || " +
          "within(@(@(@de.scrum_master.app.Annotation2 *) *) *)" +
        ")"
      )
      public void myAdvice1(JoinPoint joinPoint) {
        System.out.println(joinPoint);
      }
    }
    

    Unfortunately it does not, which seems to be an AspectJ limitation. I created Bugzilla ticket #549437 for it, which you might want to follow.

    Workaround: Annotate TestService directly.