我正在编写我的第一个注释处理器,但遇到一些琐碎的问题,但找不到任何有关它的信息。
我有一个带有注释的元素
@MyAnnotation String property;
当我将此属性作为处理器中的元素获取时,我似乎无法以任何方式获取元素的类型。在这种情况下,可能要获取代表String的Class或TypeElement实例。
我尝试使用实例化容器类型的类对象,Class.forName()
但它引发了ClassNotFoundException。我认为这是因为我无法访问包含该类的类加载器吗?
运行注释处理器时,您无权访问已编译的类。注释处理的要点是它发生在预编译中。
相反,您需要创建一个专门处理您的注释类型的注释处理器,然后使用镜像API来访问该字段。例如:
@SupportedAnnotationTypes("com.example.MyAnnotation")
public class CompileTimeAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// Only one annotation, so just use annotations.iterator().next();
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(
annotations.iterator().next());
Set<VariableElement> fields = ElementFilter.fieldsIn(elements);
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
// Validate fullTypeClassName
}
return true;
}
}
为了进行验证,您 不能 使用诸如之类的任何尚未编译的类(包括即将通过注释编译的类)MyType.class
。对于这些,您 只能 使用
字符串 。那是因为注释处理发生在称为“源生成”的预编译阶段,这使您可以在编译器使用注释运行之前生成源代码。
验证字段类型为java.lang.String
(已编译)的示例验证:
for (VariableElement field : fields) {
TypeMirror fieldType = field.asType();
String fullTypeClassName = fieldType.toString();
if (!String.class.getName().equals(fullTypeClassName)) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field type must be java.lang.String", field);
}
}
资源资源
javax.lang.model
并且不赞成使用旧API。有关更多信息,请参见此博客文章。如果您一直在使用这些javax
类,则不必担心。编辑:
我想获取字段类型以获取对该类型的注释。但这似乎不可行吗?
确实有可能!可以使用以下更多方法来完成此操作TypeMirror
:
if (fieldType.getKind() != TypeKind.DECLARED) {
processingEnv.getMessager().printMessage(
Kind.ERROR, "Field cannot be a generic type.", field);
}
DeclaredType declaredFieldType = (DeclaredType) fieldType;
TypeElement fieldTypeElement = (TypeElement) declaredFieldType.asElement();
在这里,您有两种选择:
javac
运行APT 的当前调用中被编译),则可以通过AnnotationMirror
实例引用它。已经编译
DifferentAnnotation diffAnn = fieldTypeElement.getAnnotation(
DifferentAnnotation.class);
// Process diffAnn
非常简单,这使您可以直接访问注释本身。
未编译
请注意,无论注释是否被编译,该解决方案都将起作用,它不如上面的代码那么干净。
这是我曾经编写的几个方法,用于通过其类名称从注释镜像中提取特定值:
private static <T> T findAnnotationValue(Element element, String annotationClass,
String valueName, Class<T> expectedType) {
T ret = null;
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
DeclaredType annotationType = annotationMirror.getAnnotationType();
TypeElement annotationElement = (TypeElement) annotationType
.asElement();
if (annotationElement.getQualifiedName().contentEquals(
annotationClass)) {
ret = extractValue(annotationMirror, valueName, expectedType);
break;
}
}
return ret;
}
private static <T> T extractValue(AnnotationMirror annotationMirror,
String valueName, Class<T> expectedType) {
Map<ExecutableElement, AnnotationValue> elementValues = new HashMap<ExecutableElement, AnnotationValue>(
annotationMirror.getElementValues());
for (Entry<ExecutableElement, AnnotationValue> entry : elementValues
.entrySet()) {
if (entry.getKey().getSimpleName().contentEquals(valueName)) {
Object value = entry.getValue().getValue();
return expectedType.cast(value);
}
}
return null;
}
假设您正在寻找DifferentAnnotation
注释,并且您的源代码如下所示:
@DifferentAnnotation(name = "My Class")
public class MyClass {
@MyAnnotation
private String field;
// ...
}
此代码将打印My Class
:
String diffAnnotationName = findAnnotationValue(fieldTypeElement,
"com.example.DifferentAnnotation", "name", String.class);
System.out.println(diffAnnotationName);
问题内容: 我有一个名为@Pojo的自定义注释,可用于自动生成Wiki文档: 我这样使用它: 注释资源方法,以便注释处理器可以自动生成描述所需资源和类型的Wiki页面。 我需要在注释处理器中读取该字段的值,但出现运行时错误。 在我的处理器的源代码中,我有以下几行: 但实际的类不适用于处理器。我认为我需要一个替代品来代替实际课程。我不确定该怎么买。 我得到的错误是: 该是我的一个提到的一类注释。 不
问题内容: 我正在为Eclipse构建注释处理器插件,我想做的是在处理过程中检查项目文件夹中的几个文件。 我想知道如何从处理器中获取项目路径。我相信可以这样做,因为项目源路径已提供给处理器-但我找不到找到它的方法。 我尝试查看System.properties和processingEnv.getOptions(),但那里没有有用的信息。 最终,我也想在Netbeans上使用此注释处理器,因此,如果
我正在编写一个在javac中运行的注释处理器。它扫描带注释的类并生成包含类名的资源文件。这些名称将在运行时使用,以便能够获得
需要注释处理器的帮助。我创建了一个简单的注释处理器,它使用@autoservice注释来检查注释的字段是否为最终字段。但它没有显示任何编译时错误。这是我的配置 注释: 注释处理器: pom文件: 测试文件:
背景:我有一个注释处理器,它通过扫描控制器上的Spring注释来构建改造接口。我将它设置为在基于kotlin或java的Spring应用程序中工作,它可以生成kotlin或java改造客户端接口。 问:当针对基于 kotlin 的Spring应用程序运行时,有没有办法在控制器函数上获取默认值,无论是反射式还是通过其他方式? 例如,控制器功能看起来像这样 我希望能够生成一个看起来像 我知道幕后的编译
我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?