2011-10-07 123 views
35

我有一個名爲@Pojo的自定義註解,我用自動wiki文檔生成獲得A類:Java 6的註解處理從一個註解

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) 

來標註資源方法,以便標註處理器可以自動生成一個描述它所期望的資源和類型的wiki頁面。

我需要在註釋處理器中讀取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註釋處理的文檔和/或教程似乎很少。試圖用Google搜索。

+1

沒有多少人會問這樣的問題,但對於我們這些住在(Java)Tartarus中的人來說,其他人的支持變得非常有用 – Ordiel

回答

20

你讀過這篇文章:http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/

訣竅是實際使用getAnnotation()並捕獲MirroredTypeException。令人驚訝的是,異常提供了所需類的TypeMirror。

我不知道這是一個很好的解決方案,但它是一個。在我個人看來,我會嘗試獲取MirroredType後面的類型,但我不知道這是否可能。

+1

雖然「膠帶和口香糖」浮現在腦海中。順便說一句,酷用戶名:-)。 – Ralph

32

我來這裏問完全一樣的問題。 ...和Ralph發佈的相同blog link

這是一篇很長的文章,但非常豐富。故事總結 - 有兩種方式可以實現,簡單的方法和「更正確」的方式。

這是最簡單的方法:

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起初只是超級混淆,而且心態verb散。我很想放出一個幫助課,讓所有的基本操作變得明顯...但這是另一天的故事(如果你想要的話,我可以點我)。

+0

我被困在這裏。如果你有任何問題,你能幫助你的助手發表一個要點嗎? – gorodechnyj

+1

@gorodechnyj - 這裏是我當時寫的代碼:https://github.com/ddopson/EpicFramework/blob/uiv2/EpicBuilder/src/com/epic/framework/build/EpicAnnotationProcessor.java隨意挖掘它和偷竊。 –