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

Обработка аннотации Java 6 - получение класса из аннотации

У меня есть пользовательская аннотация, называемая @Pojo, которую я использую для создания автоматической вики-документации:

package com.example.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Pojo {
    Class<?> value();
}

Я использую его следующим образом:

@Pojo(com.example.restserver.model.appointment.Appointment.class)

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

Мне нужно прочитать значение поля value в обработчике аннотаций, но я получаю ошибку времени выполнения.

В исходном коде для моего процессора у меня есть следующие строки:

final Pojo pojo = element.getAnnotation(Pojo.class);
// ...
final Class<?> pojoJavaClass = pojo.value();

но фактический класс недоступен для процессора. Думаю, мне нужен javax.lang.model.type.TypeMirror вместо этого как суррогат для настоящего класса. Я не уверен, как его получить.

Ошибка, которую я получаю:

javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror com.example.restserver.model.appointment.Appointment

Appointment - это класс, упомянутый в одной из моих аннотаций @Pojo.

К сожалению, документация и/или учебники по обработке аннотации Java кажутся скудными. Пробовал поиск в Интернете.

4b9b3361

Ответ 1

Вы читали эту статью: http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/?

Там трюк состоит в том, чтобы фактически использовать getAnnotation() и уловить исключение MirroredTypeException. Неожиданно исключение предоставляет TypeMirror требуемого класса.

Я не знаю, является ли это хорошим решением, но оно одно. По моему личному мнению, я попытался бы получить тип за MirroredType, но я не знаю, возможно ли это.

Ответ 2

Я пришел сюда, чтобы задать ТОЧНЫЙ тот же вопрос.... и нашел ту же ссылку размещенную Ральфом.

Это длинная статья, но очень богатая. Резюме истории - есть два способа сделать это, простой способ и "более правильный" способ.

Это простой способ:

private static TypeMirror getMyValue1(MyAnnotation annotation) {
    try
    {
        annotation.myValue(); // this should throw
    }
    catch( MirroredTypeException mte )
    {
        return mte.getTypeMirror();
    }
    return null; // can this ever happen ??
}

Другой более утомительный способ (без исключений):

private static AnnotationMirror getAnnotationMirror(TypeElement typeElement, Class<?> clazz) {
    String clazzName = clazz.getName();
    for(AnnotationMirror m : typeElement.getAnnotationMirrors()) {
        if(m.getAnnotationType().toString().equals(clazzName)) {
            return m;
        }
    }
    return null;
}

private static AnnotationValue getAnnotationValue(AnnotationMirror annotationMirror, String key) {
    for(Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet() ) {
        if(entry.getKey().getSimpleName().toString().equals(key)) {
            return entry.getValue();
        }
    }
    return null;
}


public TypeMirror getMyValue2(TypeElement foo) {
    AnnotationMirror am = getAnnotationMirror(foo, MyAnnotation.class);
    if(am == null) {
        return null;
    }
    AnnotationValue av = getAnnotationValue(am, "myValue");
    if(av == null) {
        return null;
    } else {
        return (TypeMirror)av.getValue();
    }
}

Конечно, как только вы получите TypeMirror, вы (по крайней мере, по моему опыту) почти всегда хотите TypeElement:

private TypeElement asTypeElement(TypeMirror typeMirror) {
    Types TypeUtils = this.processingEnv.getTypeUtils();
    return (TypeElement)TypeUtils.asElement(typeMirror);
}

... этот последний маленький неочевидный бит занял у меня час вытягивания волос, прежде чем я разобрал его в первый раз. Эти обработчики аннотаций на самом деле не так уж сложно писать, API просто сбивает с толку сначала и разумно многословно. Я соблазн выпустить класс-помощник, который делает все основные операции очевидными... но это история за другой день (если мне это нужно).