注釈プロセッサを実行しているとき、コンパイルされたクラスにアクセスすることはできません。注釈処理のポイントは、それがあらかじめコンパイルされていることです。
代わりに、注釈タイプを具体的に処理するアノテーションプロセッサを作成し、ミラーAPIを使用してフィールドにアクセスする必要があります。たとえば:
@SupportedAnnotationTypes("com.example.MyAnnotation")
public class CompileTimeAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// Only one annotation, so just use annotations.iterator().next();
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(
annotations.iterator().next());
Set<VariableElement> fields = ElementFilter.fieldsIn(elements);
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
// Validate fullTypeClassName
}
return true;
}
}
検証のために、あなたははMyType.class
のようなものを使用して(注釈付きでコンパイルされようとしているものも含めて)コンパイルする至っていない任意のクラスを使用することはできません。これらの場合は、文字列のみを使用する必要があります。これは、アノテーションを使用してコンパイラを実行する前にソースコードを生成できるようにする、「ソース生成」と呼ばれる事前コンパイル段階でアノテーション処理が行われるためです。
フィールドタイプは(既にコンパイルされている)java.lang.String
であることを確認する例検証:
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
if (!String.class.getName().equals(fullTypeClassName)) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field type must be java.lang.String", field);
}
}
リソース
編集:
私はそのタイプの注釈を取得するには、フィールドの種類を取得したいです。しかし、これは可能なようには思われませんか?
確かに可能です!これはTypeMirror
上の複数のメソッドを使用して行うことができます。
if (fieldType.getKind() != TypeKind.DECLARED) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field cannot be a generic type.", field);
}
DeclaredType declaredFieldType = (DeclaredType) fieldType;
TypeElement fieldTypeElement = (TypeElement) declaredFieldType.asElement();
ここから、次の2つの選択肢があります:あなたが見つけるためにしようとしている注釈がすでにコンパイルされている場合は(
- をすなわち、それが別のライブラリからです)、クラスを直接参照してアノテーションを取得することができます。
- 検索しようとしている注釈がコンパイルされていない(つまり、APTを実行している
javac
の現在の呼び出しでコンパイルされている)場合は、AnnotationMirror
インスタンスで参照できます。
が既に
DifferentAnnotation diffAnn = fieldTypeElement.getAnnotation(
DifferentAnnotation.class);
// Process diffAnn
非常にストレートフォワードコンパイル、これはあなたの注釈自体に直接アクセスできます。
このソリューションは関係なく、注釈がコンパイルされているかどうかの動作することを
注意をコンパイルされていない、それは上記のコードと同じようにきれいではありません。
private static <T> T findAnnotationValue(Element element, String annotationClass,
String valueName, Class<T> expectedType) {
T ret = null;
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
DeclaredType annotationType = annotationMirror.getAnnotationType();
TypeElement annotationElement = (TypeElement) annotationType
.asElement();
if (annotationElement.getQualifiedName().contentEquals(
annotationClass)) {
ret = extractValue(annotationMirror, valueName, expectedType);
break;
}
}
return ret;
}
private static <T> T extractValue(AnnotationMirror annotationMirror,
String valueName, Class<T> expectedType) {
Map<ExecutableElement, AnnotationValue> elementValues = new HashMap<ExecutableElement, AnnotationValue>(
annotationMirror.getElementValues());
for (Entry<ExecutableElement, AnnotationValue> entry : elementValues
.entrySet()) {
if (entry.getKey().getSimpleName().contentEquals(valueName)) {
Object value = entry.getValue().getValue();
return expectedType.cast(value);
}
}
return null;
}
はあなたがDifferentAnnotation
注釈を探しているとしましょうと、あなたのソースコードは次のようになります。ここでは
私はそのクラス名によって注釈ミラーから一定の値を抽出するために、一度書いたカップルの方法がありますこの:
@DifferentAnnotation(name = "My Class")
public class MyClass {
@MyAnnotation
private String field;
// ...
}
このコードはMy Class
印刷します:
String diffAnnotationName = findAnnotationValue(fieldTypeElement,
"com.example.DifferentAnnotation", "name", String.class);
System.out.println(diffAnnotationName);
'Field.getType()'を使わないのはなぜですか? – Desert
私は私の知る限り私の注釈のプリセッサのフィールドインスタンスにアクセスできないので、 –