Java 6注释处理 - 从注释中获取类

Ral*_*lph 45 java types annotation-processing

我有一个名为@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();
}
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

@Pojo(com.example.restserver.model.appointment.Appointment.class)
Run Code Online (Sandbox Code Playgroud)

注释资源方法,以便注释处理器可以自动生成描述其期望的资源和类型的Wiki页面.

我需要value在注释处理器中读取字段的值,但我收到运行时错误.

在我的处理器的源代码中,我有以下几行:

final Pojo pojo = element.getAnnotation(Pojo.class);
// ...
final Class<?> pojoJavaClass = pojo.value();
Run Code Online (Sandbox Code Playgroud)

但实际的类不适用于处理器.我想我需要一个javax.lang.model.type.TypeMirror代替真正的班级的代理人.我不确定如何获得一个.

我得到的错误是:

javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror com.example.restserver.model.appointment.Appointment
Run Code Online (Sandbox Code Playgroud)

Appointment是我的一个@Pojo注释中提到的类.

不幸的是,关于Java注释处理的文档和/或教程似乎很少.尝试使用谷歌搜索.

Dav*_*son 41

我来这里问同样的问题....并找到了拉尔夫发布的相同博客链接.

这是一篇很长的文章,但非常丰富.故事摘要 - 有两种方法可以做到,简单方法和"更正确"的方式.

这是简单的方法:

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

另一种更乏味的方式(没有例外):

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,一旦你得到一个TypeMirror,你(至少根据我的经验)几乎总是想要一个TypeElement:

private TypeElement asTypeElement(TypeMirror typeMirror) {
    Types TypeUtils = this.processingEnv.getTypeUtils();
    return (TypeElement)TypeUtils.asElement(typeMirror);
}
Run Code Online (Sandbox Code Playgroud)

......在我第一次整理出来之前,最后一点不明显的位置让我花了一个小时的时间.这些注释处理器实际上并不难写,API最初只是令人困惑,而且令人费解.我很想推出一个让所有基本操作显而易见的辅助类......但这是另一天的故事(如果你需要的话,请告诉我).

  • 我认为 +1 对于这个答案来说是不够的。应该是+10。 (2认同)

Ral*_*lph 26

您是否阅读过这篇文章:http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/

诀窍是实际使用getAnnotation()并捕获MirroredTypeException.令人惊讶的是,异常然后提供了所需类的TypeMirror.

我不知道这是一个很好的解决方案,但它是一个.在我个人看来,我会尝试获得MirroredType背后的类型,但我不知道这是否可行.