Иметь общий базовый тип для всех моих пользовательских аннотаций

Итак, я создал несколько пользовательских аннотаций:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Foo {

}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bar {

}

Эти аннотации используются в моих функциях:

public class Worker {

   @Foo
   public void doTaskOne() {...}

   @Bar
   public void doTaskX() {...}

   ...
}

Я хочу использовать отражение java, чтобы проверить, объявлена ​​​​ли определенная аннотация в одном методе.

for (Method m : methods) {
      if (m.isAnnotationPresent(Foo.class)) {
        ...
      } else if (m.isAnnotationPresent(Bar.class)) {
        ...
      }
}

Проблема в том, что, поскольку в Java пользовательская аннотация @interface не может быть расширена. Я имею в виду, что это незаконно:

public @interface Bar extends MyBaseAnnotation{
}

Это я не могу иметь базу @interface для всех моих пользовательских классов аннотаций Foo и Bar. Итак, если у меня создана новая пользовательская аннотация, мне нужно добавить больше условий else if в приведенный выше код проверки метода, что отстой! Можно ли как-то избавиться от этой проблемы? Чего я хочу добиться, так это обобщить мой код проверки метода на:

for (Method m : methods) {
     if (m.isAnnotationPresent(MyBaseAnnotation.class)) {
         ...
     }
}

Как этого достичь?


person Leem.fin    schedule 20.09.2019    source источник


Ответы (2)



При условии, что

@Parent
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Foo {}

@Parent
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Bar {}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@interface Parent {}

и есть способ

public static boolean isAnnotationPresent(Method method, Class<? extends Annotation> parentAnnotation) throws NoSuchMethodException {
    for (Annotation methodAnnotation : method.getDeclaredAnnotations()) {
        if (methodAnnotation.annotationType().isAnnotationPresent(parentAnnotation)) {
            return true;
        }
    }
    return false;
}

ты можешь сделать

isAnnotationPresent(m, Parent.class)

Вы правильно поняли: в Java нет наследования между типами аннотаций. Впрочем, вы могли бы установить свои собственные правила. Говоря «если аннотация B имеет над собой аннотацию A, то B расширяет A», вы определяете правило, которому будете следовать при использовании отражения.

person Andrew Tobilko    schedule 20.09.2019
comment
Могу ли я иметь метод в родительской аннотации, чтобы функция проверки метода могла вызывать его для всех моих аннотаций? Другими словами, все унаследованные аннотации наследуют этот метод? public @interface Parent { String value() default ""; } - person Leem.fin; 20.09.2019
comment
Нет, вы можете попробовать использовать/скопировать аналогичный механизм, который использует Spring, но он довольно сложен и требует создания всего собственного API аннотаций и реализации собственных аннотаций во время выполнения с использованием собственных прокси-классов. Так как тогда вы могли бы читать данные из родительской аннотации и копировать их в дочерние, когда используется ваш метод API. Но я бы не предложил такое хакерское решение в любой ситуации. Возможно, вместо этого попробуйте упростить использование аннотаций. - person GotoFinal; 23.09.2019
comment
Но если ты все равно захочешь это сделать, @Leem.fin, я могу еще немного помочь. - person GotoFinal; 23.09.2019