2016-12-08 7 views
2

В настоящее время я пишу процессор аннотации, который будет генерировать новый исходный код. Этот Процессор изолирован от самого приложения, поскольку это шаг в построении проекта, и я отделил всю сборную систему от приложения.Обработка аннотации неизвестна Аннотации

Здесь возникает проблема, так как я хочу обработать аннотацию, созданную в приложении. Назовите его CustomAnnotation. с полным именем com.company.api.annotation.CustomAnnotation.

В процессоре я могу искать аннотации по полному имени, что действительно приятно. Теперь я, кажется, могу получить методы, поле и т. Д., Которые аннотируются, поскольку я могу вызвать функцию getElementsAnnotatedWith с ТипElement вместо Класс.

Теперь у нашей CustomAnnotation есть поля и переменные в нем, и обычно я получаю сам аннотацию следующим образом: Class annotation = Element.getAnnotation(Class) Но я не могу использовать это, поскольку CustomAnnotation недоступен как объект класса. (Конечно, он не известен процессору) Я попытался использовать TypeMirror и другие доступные вещи, но ничего не работает.

Кто-нибудь знает, как получить Аннотацию, чтобы прочитать ее ценности?

EDIT: Давайте посмотрим на эту реализацию:

@SupportedAnnotationTypes("com.company.api.annotation.CustomAnnotation") 
@SupportedSourceVersion(SourceVersion.RELEASE_8) 
public class CustomProcessor extends AbstractProcessor 
{ 

    public CustomProcessor() 
    { 
    super(); 
    } 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) 
    { 
    TypeElement test = annotations.iterator().next(); 

    for (Element elem : roundEnv.getElementsAnnotatedWith(test)) 
    { 
     //Here is where I would get the Annotation element itself to 
     //read the content of it if I can use the Annotation as Class Object. 
     SupportedAnnotationTypes generated = elem.getAnnotation(SupportedAnnotationTypes.class); 
    } 
} 

Однако я не должен использовать CustomAnnotation.class, так как не существует в этой среде. Как я могу это сделать, не владея объектом класса?

+0

Не уверен, что вы просите ... Вы не можете сделать Class.forName () первый? – GhostCat

+2

Что случилось с ['Element.getAnnotationMirrors()'] (https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html#getAnnotationMirrors--), затем [AnnotationMirror.getElementValues ​​() '] (https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationMirror.html#getElementValues--)? – Holger

+0

Спасибо @Holger, что это то, что мне нужно! Я не нашел вопроса с этой проблемой и не знал, что getAnnotationMirrors будет тем, что мне нужно. – Nico

ответ

2

Вы можете запросить аннотации как AnnotationMirror, который не требует типа аннотаций, чтобы быть загружено временем выполнения Class:

@Override 
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
    for(TypeElement test: annotations) { 
     for(Element elem : roundEnv.getElementsAnnotatedWith(test)) { 
      System.out.println(elem); 
      for(AnnotationMirror am: elem.getAnnotationMirrors()) { 
       if(am.getAnnotationType().asElement()==test) 
        am.getElementValues().forEach((ee,av) -> 
         System.out.println("\t"+ee.getSimpleName()+" = "+av.getValue()) 
        ); 
      } 
     } 
    } 
    return true; 
} 
+0

Привет, у Хольгера был только небольшой вопрос. Итак, я использовал ваш комментарий и получил этот мир «Карта»? расширяет ExecutableElement,? extends AnnotationValue> annotationValues ​​= annotationMirrors.get (0) .getElementValues ​​(); 'и эта карта выглядит так:' Key: query(), Value: "from role r где r.deleted = false и r.name =: name ", но когда я хочу получить такое значение: AnnotationValue annotationValue = annotationValues.get (" query ");' или даже используя query() в get, все, что я получаю, это 'null'. Вы знаете, как я могу получить значение без них для циклов? – Nico

+1

На карте есть 'ExecutableElement' как ключ, поэтому поиск с помощью' String' не может работать. Поскольку ваш метод 'process' получает сам тип аннотации как' TypeElement', вы можете использовать 'getEnclosedElements()' на нем, чтобы получить объявленные элементы аннотации. Вы можете использовать их имена, чтобы проверить, какой элемент «Элемент» вам нужен. После этого вы можете использовать его повторно для поиска значения для каждого аннотированного элемента. – Holger

Смежные вопросы