Spring AOP:捕获参数注释的接口方法,但不存在注释

时间:2016-06-03 08:25:09

标签: aspectj spring-aop pointcut aspects spring-aspects

我使用Spring AOP拦截方法执行。

我的界面如下所示:

public interface MyAwesomeService {
    public Response doThings(int id, @AwesomeAnnotation SomeClass instance);
}

以下是界面的实现:

public class MyAwesomeServiceImpl implements MyAwesomeService {
    public Response doThings(int id, SomeClass instance) {
        // do something.
    }
}

现在我希望任何带有@AwesomeAnnotation注释参数的方法都应该被Spring AOP捕获。

所以我写了工作的以下方面

@Aspect
@Component
public class MyAwesomeAspect {
    @Around("myPointcut()")
    public Object doAwesomeStuff(final ProceedingJoinPoint proceedingJoinPoint) {
         final MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
         Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();

         // annotationMatrix is empty.
    }

    @Pointcut("execution(public * *(.., @package.AwesomeAnnotation  (package.SomeClass), ..))")
    public void myPointcut() {}
}

然而,当我尝试找到参数注释时,我没有得到任何注释。如上所述,annotationMatrix为空。

所以这是我的问题:

  1. 为什么annotationMatrix是空的?可能是因为参数注释不是从接口继承的。
  2. 为什么我能够捕获方法执行。由于Spring AOP能够与切入点匹配,因此Spring能够以某种方式查看方法的参数注释,但是当我尝试使用methodSignature.getMethod().getParameterAnnotations()时,它无法正常工作。

2 个答案:

答案 0 :(得分:1)

我还使用了一个参数注释来解决这个问题。我能够通过确保参数注释定义将RetentionPolicy作为RUNTIME并将Target作为PARAMETER

来修复相同的问题。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Param {

    public String name();

}

答案 1 :(得分:1)

您的问题的答案:

  1. 参数注释不会从实现方法的接口继承。事实上,如果注释类型本身由@Inherited注释,注释几乎从不继承,只能从类(不是接口!)继承,参见JDK API documentation更新:因为我之前已经多次回答过这个问题,所以我刚刚记录了问题以及Emulate annotation inheritance for interfaces and methods with AspectJ中的解决方法。

  2. 因为在编译或编织时,AspectJ可以将您的切入点与接口方法匹配,从而看到注释。

  3. 您可以通过在接口实现中向参数添加注释来修复此情况,例如:像这样:

    @Override
    public Response doThings(int id, @AwesomeAnnotation SomeClass instance) {
        // ...
    }
    

    然后用这样的方面......

    @Aspect
    @Component
    public class MyAwesomeAspect {
        @Pointcut("execution(public * *..MyAwesomeService.*(*, @*..AwesomeAnnotation (*), ..)) && args(*, instance, ..)")
        static void myPointcut(SomeClass instance) {}
    
        @Around("myPointcut(instance)")
        public Object doAwesomeStuff(Object instance, ProceedingJoinPoint proceedingJoinPoint) {
            System.out.println(proceedingJoinPoint);
            System.out.println("  instance = " + instance);
            MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
             Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
             for (Annotation[] annotations : annotationMatrix) {
                 for (Annotation annotation : annotations) {
                     System.out.println("  annotation = " + annotation);
                 }
             }
             return proceedingJoinPoint.proceed();
        }
    }
    

    ...你得到一个与此类似的控制台日志:

    execution(Response de.scrum_master.app.MyAwesomeServiceImpl.doThings(int, SomeClass))
      instance = de.scrum_master.app.SomeClass@23fc625e
      annotation = @de.scrum_master.app.AwesomeAnnotation()