对于以下自定义Java注释
@CustomAnnotation(clazz=SomeClass.class)
public class MyApplicationCode
{
...
}
我基本上希望能够在编译时同时获取MyApplicationCode的Class对象和clazz参数,以确认一些编码约定的一致性(另一个故事)。 基本上我希望能够在注释处理器中访问MyApplicationCode.class和Someclass.class代码。 我几乎就在那里,但我遗漏了一些东西。我有
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface CustomAnnotation
{
public Class clazz();
}
然后我有了处理器:
public class CustomAnnotationProcessor extends AbstractProcessor
{
private ProcessingEnvironment processingEnvironment;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment)
{
this.processingEnvironment = processingEnvironment;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment)
{
Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class);
for(Element e : elements)
{
Annotation annotation = e.getAnnotation(CustomAnnotation.class);
Class clazz = ((CustomAnnotation)annotation).clazz();
// How do I get the actual CustomAnnotation clazz?
// When I try to do clazz.getName() I get the following ERROR:
// Attempt to access Class object for TypeMirror SomeClass
// Also, how do I get the Class object for the class that has the annotation within it?
// In other words, how do I get MyApplicationCode.class?
}
}
}
所以我在process方法中尝试做的是从下面的原始代码中获取SomeClass.class和MyApplication.class,以便在编译时进行一些自定义验证。在我的生活中,我似乎无法弄清楚如何获得这两个价值......
@CustomAnnotation(clazz=SomeClass.class)
public class MyApplicationCode
更新:以下帖子有更多细节,而且距离更近了。但问题是你仍然最终得到了一个从中拉出类对象的TypeMirror对象,它没有解释:http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/
Update2:您可以通过
获取MyApplication.classString classname = ((TypeElement)e).getQualifiedName().toString();
答案 0 :(得分:1)
我打算将你指向博客http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/的方向,但看起来你已经找到了这个。
我看到你弄明白了如何访问MyApplication Element,所以我不会介绍....
您看到的异常实际上包含其中的注释属性的类型。因此,当您捕获异常时,可以引用注释clazz值:
public class CustomAnnotationProcessor extends AbstractProcessor
{
private ProcessingEnvironment processingEnvironment;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment)
{
this.processingEnvironment = processingEnvironment;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment)
{
Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class);
for(Element e : elements)
{
CustomAnnotation annotation = e.getAnnotation(CustomAnnotation.class);
TypeMirror clazzType = null;
try {
annotation.clazz();
} catch (MirroredTypeException mte) {
clazzType = mte.getTypeMirror();
}
System.out.println(clazzType); // should print out SomeClass
}
}
}
是的,这完全是一个解决方案,我不确定为什么API开发人员决定采用注释处理器功能。但是,我已经看到很多人实现了这个(包括myself),并且提到的文章也描述了这种技术。这似乎是目前可接受的解决方案。
就“抓取”MyApplicationCode和SomeClass的类值而言,如果它们是正在编译的类,则无法执行此操作。但是,您可以使用Element和TypeMirror表示对类执行某些高级验证(方法,字段,类名,存在的注释等)
答案 1 :(得分:0)
阅读此related SO question后,我发现了excellent page about the Java Annotation Processing Tool (APT)。它是从2005年开始的,所以这些天可能不是最好的方法。
APT [...]是Java的注释处理工具。更具体地说,APT允许您在代码编译过程中插入代码来处理源文件中的注释 - 在此过程中,您可以发出注释,警告和错误。
这仅适用于Oracle的JDK。
答案 2 :(得分:-1)
这是编译时间。我认为编译器甚至没有完成编译源代码。您可以从AnnotatedElement实例中检索此类信息,该实例将为您提供已注释类型的相关信息,但不提供其运行时属性,因为相关类文件尚未由虚拟机加载,因此尚未提供。并且编译器甚至不能保证在java的虚拟机下运行,因此它不能强制加载类文件。它的要求只是能够生成任何特定虚拟机可以读取的字节码。
因此,请检查镜像Api,并获取有关已注释的类/方法/字段的任何相关信息,请检查表示该实例的AnnotatedElement。
另外注意:这是信息正是我所理解的,所以它可能不是真正的事实。