Подтвердить что ты не робот

@AspectJ pointcut для методов, которые переопределяют метод интерфейса с аннотацией

Как я могу написать pointcut pointce, который применяется к методам выполнения, которые переопределяют метод интерфейса с аннотацией? Например:

interface A {
  @MyAnnotation void method();
}
class B implements A {
  void method();
}

Точечный execution(@MyAnnotation * *.*(..)) соответствует только если B.method() несет самую аннотацию. Есть ли другой способ сделать это?

4b9b3361

Ответ 1

Как отметил Николас, это невозможно в AspectJ. Вот еще одно доказательство того, почему это невозможно (взято из http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html раздел Аннотации Наследование и сопоставление точечных ссылок):

В соответствии с спецификацией Java 5 аннотации не-типа не наследуются, а аннотации по типам наследуются только в том случае, если они имеют метаинформацию @Inherited. Вызов c2.aMethod(это будет b.method() в вашем примере) не сопоставляется, поскольку сопоставление точек соединения для модификаторов (модификаторы видимости, аннотации и броски) основано на объекте точки соединения ( метод, фактически вызываемый).

Пострадав от этой же проблемы, я написал небольшой метод/библиотеку, которая позволит вам писать pointcut для таких методов. Вот как это будет работать для вашего примера:

myAnnotationIsExecuted(): execution(public * *.*(..)) && 
             if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));

ИЛИ

myAnnotationIsExecuted(): execution(public * A+.*(..)) &&
             if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));

Метод implementsAnnotation(String,JoinPoint) поступает из библиотеки; базовый метод, который проверяет, содержат ли реализованные методы указанную аннотацию.

Более подробную информацию о методе/библиотеке можно найти здесь.

Ответ 2

Обновление

Так как кажется, что это невозможно сделать в Spring (см. оригинальный ответ), я бы сказал, что вам нужно добавить аннотацию к каждому методу реализующих классов. Существует очевидный способ сделать это, но я полагаю, что если вы ищете более автоматический способ, вам нужно будет написать его самостоятельно.

Я могу представить себе какой-то домашний постпроцессор, который будет искать конкретную аннотацию, скажем @ApplyThisAnnotationToAllWhoInheritMe. Как только он найдет эту аннотацию, он будет сканировать исходный код для наследования членов и добавлять необходимую аннотацию, когда это необходимо, до компиляции.

Независимо, если вы используете Spring AOP для этого, похоже, что это должно быть на методе реализации. Если классы, на которые вы надеетесь, это поможет, вы не можете контролировать свой инструмент Spring AOP.

Оригинальный ответ

Из Spring 3.0 Документация:

AspectJ следует правилу Java, что аннотации на интерфейсах не наследуются.

Я нашел этот бит в разделе 7.8.2 Other Spring aspects for AspectJ, который является частью 7.8 Using AspectJ with Spring applications, что заставляет меня думать, что это глобальное правило.

Ответ 3

//introducing empty marker interface
declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker;

public pointcut p1() : execution(* TrackedParentMarker+.*(..));

Также вы должны включить флаг компилятора -XhasMember.