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

Как получить имя класса аннотации, значения атрибута с использованием отражения

Я знаю, что если мы знаем класс аннотаций, мы можем легко получить конкретную аннотацию и получить доступ к ее атрибуту. Например:

field.getAnnotation(Class<T> annotationClass) 

Который будет возвращать ссылку на конкретный интерфейс аннотации, чтобы вы могли легко получить доступ к его значениям.

Мой вопрос, если у меня нет предварительных знаний о конкретном классе аннотаций. Я просто хочу использовать отражение, чтобы получить все имена классов аннотаций и их атрибуты во время выполнения с целью выгрузки информации о классе, например, в виде файла JSON. Как я могу сделать это простым способом.

Annotation[] field.getAnnotations();

Этот метод возвращает только динамические прокси интерфейсов аннотаций.

4b9b3361

Ответ 1

Вопреки ожиданиям, элементы аннотации не являются атрибутами - на самом деле это методы, которые возвращают предоставленное значение или значение по умолчанию.

Вы должны перебирать методы аннотаций и вызывать их, чтобы получить значения. Используйте annotationType(), чтобы получить класс аннотаций, объект, возвращаемый getClass(), является просто прокси.

Вот пример, который печатает все элементы и их значения аннотации @Resource класса:

@Resource(name = "foo", description = "bar")
public class Test {

    public static void main(String[] args) throws Exception {

        for (Annotation annotation : Test.class.getAnnotations()) {
            Class<? extends Annotation> type = annotation.annotationType();
            System.out.println("Values of " + type.getName());

            for (Method method : type.getDeclaredMethods()) {
                Object value = method.invoke(annotation, (Object[])null);
                System.out.println(" " + method.getName() + ": " + value);
            }
        }

    }
}

Выход:

Values of javax.annotation.Resource
 name: foo
 type: class java.lang.Object
 lookup: 
 description: bar
 authenticationType: CONTAINER
 mappedName: 
 shareable: true

Спасибо Аарону за указание на то, что вам нужно привести аргумент null, чтобы избежать предупреждений.

Ответ 2

Просто для ответа на ответ выше (у меня недостаточно ответов, чтобы ответить на него):

method.invoke(annotation, null)

следует изменить на следующее, иначе оно выдает исключение:

method.invoke(annotation, (Object[])null) or method.invoke(annotation, new Object[0])