Java6注释处理——从注释中获取类
我有一个名为@Pojo的自定义注释,用于自动生成wiki文档: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
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());