2016-06-03 12 views
1

Я использую Spring AOP для перехвата выполнения метода.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() {} 
} 

Однако, когда я пытаюсь найти аннотации параметров, я не получаю никаких аннотаций назад. Как упоминалось выше, аннотационная матрица пуста.

Так вот мои вопросы:

  1. Почему является annotationMatrix пустой? Вероятно, потому что аннотации параметров не наследуются от интерфейса.
  2. Почему я могу захватить выполнение метода. Поскольку Spring AOP способен сопоставлять pointcut, Spring каким-то образом может видеть аннотации параметров метода, но когда я пытаюсь увидеть, что использование methodSignature.getMethod().getParameterAnnotations() не работает.

ответ

1

Ответов на вопросы:

  1. параметры аннотации не унаследованные от интерфейсов к методам реализации. Фактически, аннотации почти никогда не унаследованы, а только от класса (а не интерфейса!) До подкласса, если аннотация аннотируется аннотацией @Inherited, см. JDK API documentation. Обновление: Поскольку я уже несколько раз отвечал на этот вопрос, я только что задокументировал проблему, а также обходной путь в Emulate annotation inheritance for interfaces and methods with AspectJ.

  2. Потому что во время компиляции или переплетения AspectJ может соответствовать вашему pointcut против метода интерфейса и, таким образом, видит аннотацию.

Вы можете исправить ситуацию, добавив аннотацию к параметру в реализации интерфейса, например. как это:

@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 = [email protected] 
    annotation = @de.scrum_master.app.AwesomeAnnotation() 
+0

Спасибо за ваш ответ. Я подозревал, что AspectJ, вероятно, смотрит на интерфейс, чтобы обнаружить аннотации. И так как во время выполнения аннотация из интерфейса не переносится, я не видел никакой информации о аннотации. Я решил эту проблему немного иначе, чем то, как вы указали. Я смотрю на интерфейс, чтобы увидеть, присутствует ли аннотация в определении интерфейса. – n00bc0der

0

Я также столкнулся с этой проблемой с одним из аннотаций параметра. Я был в состоянии исправить то же самое, убедившись, что определение параметров аннотаций было RetentionPolicy, как RUNTIME и Target в качестве параметра

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

    public String name(); 

} 
+0

Да, аннотации имеют правильную цель и удержание:

 @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface AwesomeAnnotation { long value() default -1; } 
n00bc0der