Search code examples
springexpressionaop

Spring AOP execution - match method with specific parameter annotation and type


Given the following method:

public void doSth(@AnnotationA @AnnotationB SomeType param) {
  ...do sth...
}

and @Aspect with the following @Around advice:

@Around("execution(* *(.., @com.a.b.AnnotationA (*), ..))") 

Is there any possibility to modify the above expression to match a method with a parameter annotated with the @AnnotationA and with the SomeType type and to wildcard anything that would be between those two and before AnnotationA?

Something like (* @com.a.b.AnnotationA * SomeType) so the following methods would be matched:

doSth(@AnnotationA @AnnotationB SomeType param) 
doSth(@AnnotationB @AnnotationA SomeType param) 
doSth(@AnnotationA SomeType param) 

Thanks in advance.


Solution

  • Helper classes:

    package de.scrum_master.app;
    
    public class SomeType {}
    
    package de.scrum_master.app;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Retention;
    
    @Retention(RUNTIME)
    public @interface AnnotationA {}
    
    package de.scrum_master.app;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Retention;
    
    @Retention(RUNTIME)
    public @interface AnnotationB {}
    

    Driver application:

    package de.scrum_master.app;
    
    public class Application {
      public static void main(String[] args) {
        Application application = new Application();
        SomeType someType = new SomeType();
        application.one(11, someType, "x");
        application.two(someType, new Object());
        application.three(12.34D, someType);
        application.four(22, someType, "y");
        application.five(56.78D, someType);
      }
    
      // These should match
      public void one(int i, @AnnotationA @AnnotationB SomeType param, String s) {}
      public void two(@AnnotationB @AnnotationA SomeType param, Object o) {}
      public void three(double d, @AnnotationA SomeType param) {}
    
      // These should not match
      public void four(int i, @AnnotationB SomeType param, String s) {}
      public void five(double d, SomeType param) {}
    }
    

    Aspect:

    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 MyAspect {
      @Before("execution(* *(.., @de.scrum_master.app.AnnotationA (de.scrum_master.app.SomeType), ..))")
      public void intercept(JoinPoint joinPoint) {
        System.out.println(joinPoint);
      }
    }
    

    Console log:

    execution(void de.scrum_master.app.Application.one(int, SomeType, String))
    execution(void de.scrum_master.app.Application.two(SomeType, Object))
    execution(void de.scrum_master.app.Application.three(double, SomeType))