2016-12-08 1 views
2

현재 새 소스 코드를 생성하는 어노테이션 프로세서를 작성 중입니다. 이 프로세서는 프로젝트를 구축하는 단계이기 때문에 애플리케이션 자체와 분리되어 있으며 애플리케이션에서 전체 빌드 시스템을 분리했습니다.어노테이션 처리 알 수 없음

응용 프로그램에서 작성된 주석을 처리하기 때문에 문제가 시작됩니다. 그것을 CustomAnnotation이라고 부르 자. 정규화 된 이름 com.company.api.annotation.CustomAnnotation.

프로세서에서 정규화 된 이름으로 주석을 검색 할 수 있습니다. 정말 멋진 기능입니다. 이제 함수를 호출 할 수 있기 때문에 메소드, 필드 등을 주석 처리 할 수있는 것 같습니다. getElementsAnnotatedWithTypeElement 대신 클래스 대신.

이제 CustomAnnotation에 필드와 변수가 포함되어 있으며 보통 다음과 같은 주석 자체를 얻습니다. Class annotation = Element.getAnnotation(Class) CustomAnnotation을 클래스 객체로 사용할 수 없으므로 사용할 수 없습니다. (물론, 프로세서에 알려지지 않았기 때문에 사용할 수 없습니다.) TypeMirror 및 기타 사용 가능한 것들을 사용해 보았지만 아무것도 작동하지 않는 것 같습니다.

주석을 가져 와서 값을 읽는 방법을 아는 사람이 있습니까?

편집 : 의이 구현 살펴 보자 :

@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를 사용할 필요가 없습니다. 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

당신은로드 된 런타임 Class에게로 주석 형을 필요로하지 않습니다 AnnotationMirror로 주석을 조회 할 수 있습니다

@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

안녕하세요 홀가가 조금 질문이 있습니다. 그래서 나는 당신의 의견을 사용하고이 평화'지도 annotationValue = annotationMirrors.get (0) .getElementValues ​​();'이 맵은 다음과 같이 보입니다 : RoleR로부터의 Key : query(), Value : "r.deleted = false 및 r.name = : name "하지만이 값을 얻으려면 : AnnotationValue annotationValue = annotationValues.get ("query "); 또는 get에서 query()를 사용하는 경우에도 모두 null입니다. 이러한 루프가없는 값을 어떻게 얻을 수 있는지 알고 있습니까? – Nico

+1

지도는'ExecutableElement'를 키로 가지고 있기 때문에'String'을 이용한 검색이 작동하지 않습니다. 당신의'process' 메쏘드는 주석 유형 자체를'TypeElement'으로 받아들이므로'getEnclosedElements()'를 사용하여 선언 된 주석 멤버를 얻을 수 있습니다. 이름을 사용하여 필요한 '요소'를 확인할 수 있습니다. 일단 주석이 있으면 각 주석 요소의 값을 찾기 위해 반복적으로 사용할 수 있습니다. – Holger