Java6注释处理——从注释中获取类

Java6注释处理——从注释中获取类,java,types,annotation-processing,Java,Types,Annotation Processing,我有一个名为@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(RetentionPo

我有一个名为@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();
}
对资源方法进行注释,以便注释处理程序可以自动生成一个wiki页面,该页面描述它所需的资源和类型

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

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

final Pojo pojo = element.getAnnotation(Pojo.class);
// ...
final Class<?> pojoJavaClass = pojo.value();
约会是我的@Pojo注释中提到的一个类


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

你读过这篇文章吗:

这里的技巧是实际使用getAnnotation并捕获MirroredTypeException。令人惊讶的是,异常随后提供了所需类的TypeMirror


我不知道这是否是一个好的解决方案,但它是一个。在我个人看来,我会尝试在MirroredType后面添加类型,但我不知道这是否可行。

我来这里是想问同样的问题。。。发现拉尔夫也发了同样的帖子

这是一篇很长的文章,但内容非常丰富。故事摘要——有两种方法,简单的方法和更正确的方法

这是一个简单的方法:

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();
    }
}

。。。最后一点不明显的地方花了我一个小时的时间,我才第一次整理好。这些注释处理器实际上一点也不难编写,API一开始非常混乱,而且非常冗长。我很想推出一个助手类,让所有的基本操作都变得显而易见。。。但如果你愿意,这是另一天的故事。我的答案基本上与Dave Dopson的答案相同,只是代码有点改变:

public default Optional<? extends AnnotationMirror> getAnnotationMirror( final Element element, final Class<? extends Annotation> annotationClass )
{
    final var annotationClassName = annotationClass.getName();
    final Optional<? extends AnnotationMirror> retValue = element.getAnnotationMirrors().stream()
        .filter( m -> m.getAnnotationType().toString().equals( annotationClassName ) )
        .findFirst();

    return retValue;
}
Dave使用Element.getElementValues获取注释值,但这只返回显式应用于具体注释的值。默认值将被忽略。 方法Elements.getElementValuesWithDefaults也将返回默认值,正如您可能已经从其名称猜到的那样。

这是我的窍门:

public class APUtils {

  @FunctionalInterface
  public interface GetClassValue {
    void execute() throws MirroredTypeException, MirroredTypesException;
  }

  public static List<? extends TypeMirror> getTypeMirrorFromAnnotationValue(GetClassValue c) {
    try {
      c.execute();
    }
    catch(MirroredTypesException ex) {
      return ex.getTypeMirrors();
    }
    return null;
  }

}
注释处理器中的用法

MyAnnotationType a = element.getAnnotation(MyAnnotationType.class);
List<? extends TypeMirror> types = APUtils.getTypeMirrorFromAnnotationValue(() -> a.value());

使用JDK1.8.0_192测试,这可能会起作用,不过我想到的是胶带和口香糖。顺便说一句,很酷的用户名:-。我也被困在这里了。如果你做了什么,你能和你的助手发布一个要点吗?@gorodechnyj-这是我当时正在写的代码:随便翻找,然后自由地偷。我认为+1对于这个答案是不够的。它应该是+10。@MohamedelBeltagy-非常感谢你的好话!这是很棒的东西。我只能同意@MohamedEl Beltagy。这里是另一篇关于同一主题的优秀文章,供感兴趣的人阅读。没有多少人会问这样的问题,但是对于我们这些生活在Java Tartarus的人来说,其他人的支持变得非常有用class[]value default{};正是我要找的!
public default Optional<? extends AnnotationMirror> getAnnotationMirror( final Element element, final Class<? extends Annotation> annotationClass )
{
    final var annotationClassName = annotationClass.getName();
    final Optional<? extends AnnotationMirror> retValue = element.getAnnotationMirrors().stream()
        .filter( m -> m.getAnnotationType().toString().equals( annotationClassName ) )
        .findFirst();

    return retValue;
}
public default Optional<? extends AnnotationValue> getAnnotationValue( final AnnotationMirror annotationMirror, final String name )
{
    final Elements elementUtils = this.processingEnv.getElementUtils();
    final Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = elementUtils.getElementValuesWithDefaults( annotationMirror );
    final Optional<? extends AnnotationValue> retValue = elementValues.keySet().stream()
        .filter( k -> k.getSimpleName().toString().equals( name ) )
        .map( k -> elementValues.get( k ) )
        .findAny();

    return retValue;
}
public class APUtils {

  @FunctionalInterface
  public interface GetClassValue {
    void execute() throws MirroredTypeException, MirroredTypesException;
  }

  public static List<? extends TypeMirror> getTypeMirrorFromAnnotationValue(GetClassValue c) {
    try {
      c.execute();
    }
    catch(MirroredTypesException ex) {
      return ex.getTypeMirrors();
    }
    return null;
  }

}
public @interface MyAnnotationType {
  public Class<?>[] value() default {};
}
@MyAnnotationType(String.class)
public class Test { ... }
MyAnnotationType a = element.getAnnotation(MyAnnotationType.class);
List<? extends TypeMirror> types = APUtils.getTypeMirrorFromAnnotationValue(() -> a.value());