Java AnnotationProcessing - 获取注释的字段
Java AnnotationProcessing - Get fields of the Annotation
我根据 API AnnotationProcessing 有一个问题。
这是一个小例子。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface MyAnnotation
{
String strNumberOne() default "";
String strNumberTwo() default "";
String strNumberThree() default "";
}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
// I do not know how to beginn here
return true;
}
}
public class MyClass
{
@MyAnnotation(strNumberOne="one", strNumberTwo= "two")
private String strARandomString;
}
现在我想读取注释中声明的字段,如果有未声明的字段,我的程序应该采用默认值。
我想在列表中写入值。最后我的列表应该是这样的:
LinkedList<String> s = new LinkedList<>();
s.add(strNumberOne); // "one"
s.add(strNumberTwo); // "two"
s.add(strNumberThree); // (default) ""
我该怎么做?我找到了一种可以提供帮助的方法。它在接口 "Elements" 中,方法名称是 "getElementValuesWithDefaults()"。但是不知道怎么用。。
我也想知道 TypeElement 和 Element 之间有什么区别。
我感谢每一个答案! :)
此致!
如果 MyAnnotation
是你的处理器支持的注释,那么你只需要这样写:
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
if (shouldClaim(annotations)) {
for (Element e : env.getElementsAnnotatedWith(MyAnnotation.class)) {
MyAnnotation a = e.getAnnotation(MyAnnotation.class);
String str1 = a.strNumberOne();
String str2 = a.strNumberTwo();
String str3 = a.strNumberThree();
// Add them to a List or whatever you need.
}
return true;
}
return false;
}
private boolean shouldClaim(Set<? extends TypeElement> annotations) {
Set<String> supported = getSupportedAnnotationTypes();
for (TypeElement a : annotations) {
if (supported.contains(a.getQualifiedName().toString()))
return true;
}
return false;
}
shouldClaim
方法的逻辑在 process
. It would be more complicated if your annotation supports e.g. *
or a type of the form name.*
, but in general you don't. (See getSupportedAnnotationTypes
的文档中进行了解释,以说明其含义。)
如果MyAnnotation
不是你的处理器支持的注释,那么你将需要通过getElementValuesWithDefaults
if 它是您正在编译的包中声明的类型。因为注释处理发生在编译期间,class文件对于正在编译的源文件还不存在,这就是为什么我们使用Element
API 相反。
Element
表示某种声明,例如 class、方法或变量。 TypeElement
表示 class、接口、枚举或注解类型声明。 TypeElement
类似于 Class
我们可以用它做什么,除了我们可以使用 TypeElement
来代替 class ,而 class 不一定要编译。
要通过元素 API 获取注释值,您可以这样做:
Elements elements = processingEnv.getElementUtils();
TypeElement myAnnotation = elements.getTypeElement("com.example.MyAnnotation");
for (Element e : env.getElementsAnnotatedWith(myAnnotation)) {
for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
DeclaredType annotationType = mirror.getAnnotationType();
Element annotationDecl = annotationType.asElement();
if (myAnnotation.equals(annotationDecl)) {
Map<? extends ExecutableElement, ? extends AnnotationValue> values =
elements.getAnnotationValuesWithDefaults(mirror);
String str1 = (String) getValue(values, "strNumberOne");
String str2 = (String) getValue(values, "strNumberTwo");
String str3 = (String) getValue(values, "strNumberThree");
// ...
}
}
}
private Object getValue(Map<? extends ExecutableElement,
? extends AnnotationValue> values,
String name) {
for (Map.Entry<? extends ExecutableElement,
? extends AnnotationValue> e : values.entrySet()) {
if (name.contentEquals(e.getKey().getSimpleName()))
return e.getValue().getValue();
}
return null;
}
这很痛苦,但我们只需要使用元素 API if 我们感兴趣的注解是 classes 之一正在编译中。
我们可能还想找到 AnnotationMirror
and/or AnnotationValue
使用 Messager.printMessage
重载之一在特定元素上引起某种消息上述对象之一作为参数。
我根据 API AnnotationProcessing 有一个问题。 这是一个小例子。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface MyAnnotation
{
String strNumberOne() default "";
String strNumberTwo() default "";
String strNumberThree() default "";
}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
// I do not know how to beginn here
return true;
}
}
public class MyClass
{
@MyAnnotation(strNumberOne="one", strNumberTwo= "two")
private String strARandomString;
}
现在我想读取注释中声明的字段,如果有未声明的字段,我的程序应该采用默认值。
我想在列表中写入值。最后我的列表应该是这样的:
LinkedList<String> s = new LinkedList<>();
s.add(strNumberOne); // "one"
s.add(strNumberTwo); // "two"
s.add(strNumberThree); // (default) ""
我该怎么做?我找到了一种可以提供帮助的方法。它在接口 "Elements" 中,方法名称是 "getElementValuesWithDefaults()"。但是不知道怎么用。。 我也想知道 TypeElement 和 Element 之间有什么区别。 我感谢每一个答案! :)
此致!
如果 MyAnnotation
是你的处理器支持的注释,那么你只需要这样写:
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
if (shouldClaim(annotations)) {
for (Element e : env.getElementsAnnotatedWith(MyAnnotation.class)) {
MyAnnotation a = e.getAnnotation(MyAnnotation.class);
String str1 = a.strNumberOne();
String str2 = a.strNumberTwo();
String str3 = a.strNumberThree();
// Add them to a List or whatever you need.
}
return true;
}
return false;
}
private boolean shouldClaim(Set<? extends TypeElement> annotations) {
Set<String> supported = getSupportedAnnotationTypes();
for (TypeElement a : annotations) {
if (supported.contains(a.getQualifiedName().toString()))
return true;
}
return false;
}
shouldClaim
方法的逻辑在 process
. It would be more complicated if your annotation supports e.g. *
or a type of the form name.*
, but in general you don't. (See getSupportedAnnotationTypes
的文档中进行了解释,以说明其含义。)
如果MyAnnotation
不是你的处理器支持的注释,那么你将需要通过getElementValuesWithDefaults
if 它是您正在编译的包中声明的类型。因为注释处理发生在编译期间,class文件对于正在编译的源文件还不存在,这就是为什么我们使用Element
API 相反。
Element
表示某种声明,例如 class、方法或变量。 TypeElement
表示 class、接口、枚举或注解类型声明。 TypeElement
类似于 Class
我们可以用它做什么,除了我们可以使用 TypeElement
来代替 class ,而 class 不一定要编译。
要通过元素 API 获取注释值,您可以这样做:
Elements elements = processingEnv.getElementUtils();
TypeElement myAnnotation = elements.getTypeElement("com.example.MyAnnotation");
for (Element e : env.getElementsAnnotatedWith(myAnnotation)) {
for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
DeclaredType annotationType = mirror.getAnnotationType();
Element annotationDecl = annotationType.asElement();
if (myAnnotation.equals(annotationDecl)) {
Map<? extends ExecutableElement, ? extends AnnotationValue> values =
elements.getAnnotationValuesWithDefaults(mirror);
String str1 = (String) getValue(values, "strNumberOne");
String str2 = (String) getValue(values, "strNumberTwo");
String str3 = (String) getValue(values, "strNumberThree");
// ...
}
}
}
private Object getValue(Map<? extends ExecutableElement,
? extends AnnotationValue> values,
String name) {
for (Map.Entry<? extends ExecutableElement,
? extends AnnotationValue> e : values.entrySet()) {
if (name.contentEquals(e.getKey().getSimpleName()))
return e.getValue().getValue();
}
return null;
}
这很痛苦,但我们只需要使用元素 API if 我们感兴趣的注解是 classes 之一正在编译中。
我们可能还想找到 AnnotationMirror
and/or AnnotationValue
使用 Messager.printMessage
重载之一在特定元素上引起某种消息上述对象之一作为参数。