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

2022-08-31 17:35:04

我有一个名为@Pojo的自定义注释,我用它来自动生成wiki文档:

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注释处理的文档和/或教程似乎很少。尝试谷歌搜索。


答案 1

我来这里问完全相同的问题。...并找到了Ralph发布的相同博客链接

这是一篇很长的文章,但非常丰富。故事的总结 - 有两种方法可以做到这一点,简单的方法和“更正确”的方法。

这是简单的方法:

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起初只是超级混乱,而且冗长。我很想推出一个帮助器类,使所有基本操作都变得明显......但这是另一天的故事(如果你想要的话,请给我留言)。


答案 2

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

诀窍是实际使用getAnnotation()并捕获MirroredTypeException。令人惊讶的是,异常随后提供了所需类的类型镜像。

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