1

我正在使用 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()它时不起作用。
4

2 回答 2

2

我的一个参数注释也遇到了这个问题。我能够通过确保参数注释定义将 RetentionPolicy 作为 RUNTIME 并将 Target 作为 PARAMETER 来修复相同的问题

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Param {

    public String name();

}
于 2016-06-25T04:19:54.017 回答
1

您的问题的答案:

  1. 参数注释不会从接口继承到实现方法。事实上,注解几乎从不被继承,如果注解类型本身被注解,只能从类(不是接口!)到子类@Inherited,请参阅JDK API 文档更新:因为我之前已经多次回答过这个问题,所以我刚刚记录了这个问题,并且还记录了使用 AspectJ 模拟接口和方法的注释继承的解决方法。

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

您可以通过将注释添加到接口实现中的参数来解决这种情况,例如:

@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()
于 2016-07-02T16:35:13.700 回答