Java 6注解处理——从注解获取类
我有一个名为 @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 注释处理的文档和/或教程似乎很少。尝试过谷歌搜索。
I have an custom annotation called @Pojo which I use for automatic wiki documentation generation:
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();
}
I use it like this:
@Pojo(com.example.restserver.model.appointment.Appointment.class)
to annotation a resource method so that the annotation processor can automatically generate a wiki page describing the resource and type that it expects.
I need to read the value of the value
field in an annotation processor, but I am getting a runtime error.
In the source code for my processor I have the following lines:
final Pojo pojo = element.getAnnotation(Pojo.class);
// ...
final Class<?> pojoJavaClass = pojo.value();
but the actual class in not available to the processor. I think I need a javax.lang.model.type.TypeMirror
instead as a surrogate for the real class. I'm not sure how to get one.
The error I am getting is:
javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror com.example.restserver.model.appointment.Appointment
The Appointment
is a class mentioned in one of my @Pojo
annotation.
Unfortunately, document and/or tutorials on Java annotation processing seems scarce. Tried googling.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我来这里是为了问完全相同的问题。 ...并发现相同的 博客链接由拉尔夫发布。
文章很长,但是内容很丰富。故事摘要——有两种方法可以做到这一点,简单的方法和“更正确”的方法。
这是简单的方法:
另一种更乏味的方法(无一例外):
当然,一旦你得到了 TypeMirror,你(至少以我的经验)几乎总是想要一个 TypeElement 来代替:
...最后一点不明显在我第一次把它解决之前,我花了一个小时的时间来拉头发。这些注释处理器实际上并不难编写,只是 API 一开始非常令人困惑,而且冗长得令人费解。我很想推出一个帮助程序类,使所有基本操作变得显而易见......但这是另一天的故事(如果你想要的话,请给我留言)。
I came here to ask the EXACT same question. ... and found the same blog link posted by Ralph.
It's a long article, but very rich. Summary of the story -- there's two ways to do it, the easy way, and the "more right" way.
This is the easy way:
The other more tedious way (without exceptions):
Of course, once you get a TypeMirror, you (at least in my experience) pretty much always want a TypeElement instead:
... that last little non-obvious bit took me an hour of hair pulling before I sorted it out the first time. These annotation processors are actually not that hard to write at all, the API's are just super confusing at first and mindbendingly verbose. I'm tempted to put out a helper class that makes all the basic operations obvious ... but that's a story for another day (msg me if you want it).
您读过这篇文章吗: http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/?
我不知道这是否是一个好的解决方案,但它是一个。以我个人的观点,我会尝试获取 MirroredType 背后的类型,但我不知道这是否可能。
Have you read this article: http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/ ?
I don't know if this is a good solution, but it is one. In my personal opinion I would try to get the type behind the MirroredType, but I don't know if this is possible.
我的回答与 Dave Dopson 的基本相同,只是代码稍作改动:
他的代码使用
TypeElement
作为getAnnotationMirror()
第一个参数的类型,限制该方法仅用于类。将其更改为Element
使其可用于任何带注释的元素。使用基于流的实现而不是原始的 for 循环只是一个品味问题。
Dave 使用 Element.getElementValues() 来获取注释值,但这仅返回那些显式应用于具体注释的值。默认值将被省略。
方法
Elements.getElementValuesWithDefaults()
还将返回默认值(您可能已经从它的名称中猜到了)。My answer is basically the same as that from Dave Dopson, only the code was changed a bit:
His code used
TypeElement
as the type for the first argument ofgetAnnotationMirror()
, limiting the use of the method for classes only. Changing that toElement
makes it useable for any annotated element.Using an implementation based on streams instead of the original
for
loop is just a matter of taste.Dave used
Element.getElementValues()
to get the annotation values, but this returns only those values that were explicitly applied to the concrete annotation. The defaults will be omitted.The method
Elements.getElementValuesWithDefaults()
will return also the defaults (as you may have guessed already from the name of it).这是我的技巧:
然后我可以与任何注释值一起使用:
示例
注释处理器中的
用法使用 JDK 1.8.0_192 进行测试
This is my trick:
Then I can use with any Annotation value:
Example
Usage in annotation processor
Tested with JDK 1.8.0_192