注解处理未知注解。

4

目前我正在编写一个注解处理器,它将生成新的源代码。该处理器与应用程序本身隔离,因为它是构建项目的一步,我将整个构建系统从应用程序中分离出来。

这就是问题所在,因为我想处理在应用程序中创建的注解。让我们将其命名为CustomAnnotation,完全限定名称为com.company.api.annotation.CustomAnnotation

在处理器中,我可以通过完全限定名称搜索注解,这真的很好。现在我似乎能够获取已注释的方法、字段等,因为我可以使用TypeElement而不是Class调用函数getElementsAnnotatedWith

现在我们的CustomAnnotation有字段和变量,通常我会像这样获取注解本身:Class annotation = Element.getAnnotation(Class)但我不能使用这个,因为CustomAnnotation不可用作Class对象。(当然,处理器不知道它)我尝试使用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对象的情况下,我该如何实现呢?


不确定你在问什么... 你不能先执行 Class.forName() 吗? - GhostCat
2
Element.getAnnotationMirrors()有什么问题,接下来是AnnotationMirror.getElementValues() - Holger
谢谢@Holger,这正是我所需要的!!我没有找到一个关于这个问题的问题,并不知道getAnnotationMirrors会是我需要的。 - Nico
1个回答

3
你可以查询注解作为 AnnotationMirror,这不要求注解类型是一个已加载的运行时 Class
@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;
}

嗨,Holger,我有一个小问题。我使用了你的评论,并且有了这个片段:Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues = annotationMirrors.get(0).getElementValues(); 这个 map 看起来是这样的: Key: query(), Value: "from role r where r.deleted = false and r.name = :name" 但是当我想要获取值时,像这样: AnnotationValue annotationValue = annotationValues.get("query"); 或者使用 query() 的方式进行获取,结果都是 null。你知道我怎么在不使用循环的情况下获取到这个值吗? - Nico
1
地图的键是ExecutableElement,所以无法使用String进行查找。由于您的process方法接收注解类型本身作为TypeElement,您可以在其上使用getEnclosedElements()来获取声明的注解成员。您可以使用它们的名称来检查哪个Element是您需要的键。一旦找到它,您可以重复使用它来查找每个带注解的元素的值。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接