在下面的情况下,我想获取
MyString.class
的值,因为 @RendererType
在注释处理器执行内部的字段上具有值 TEXT
。
这是我的自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Renderer {
RendererType value() default RendererType.TEXT;
}
其中包含一个
RendererType
枚举,其定义是:
public enum RendererType {
TEXT(new Class[] {MyString.class}),
TEXTAREA(new Class[] {MyString.class}),
CHECKBOX(new Class[] {MyBoolean.class});
private final Class<?>[] supportedTypes;
RendererType(Class<?>[] classes) {
this.supportedTypes = classes;
}
public Class<?>[] getSupportedTypes() {
return this.supportedTypes;
}
}
在 POJO 中的字段上使用
@Renderer
的示例如下:
@Renderer(RendererType.CHECKBOX)
boolean old = true;
这是注释处理器
StringProcessor
,用于@Renderer
注释:
import com.company.annotation.metadata.Renderer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
public class StringProcessor extends AbstractProcessor {
private Messager messager;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
messager = processingEnv.getMessager();
}
@Override
public boolean process(
final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
for (TypeElement typeElement : annotations) {
for (Element element : roundEnv.getElementsAnnotatedWith(typeElement)) {
TypeMirror typeMirror = element.asType();
ElementKind elementKind = element.getKind();
if (elementKind.equals(ElementKind.FIELD)) {
System.out.println("FIELD");
// Do something to get `supportedTypes` associated with the enum value
}
}
}
return false;
}
@Override
public Set<String> getSupportedAnnotationTypes() {
final Set<String> annotations = new HashSet<>(Arrays.asList(Renderer.class.getName()));
return annotations;
}
}
如果您的注释处理器可以在编译时访问
Renderer
,那么最简单的方法是使用带有 AnnotatedConstruct#getAnnotation(Class)
的类文字。这将为您提供一个 Renderer
的实例,然后您可以像平常一样使用它。
package com.example.processing;
import com.example.Renderer;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
// replace source version as needed
@SupportedSourceVersion(SourceVersion.RELEASE_21)
// or override 'getSupportedAnnotationTypes'
@SupportedAnnotationTypes("com.example.Renderer")
public class RendererProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(Renderer.class)) {
// no need to verify element is field due to @Target meta-annotation
Renderer renderer = element.getAnnotation(Renderer.class);
Class<?>[] supportedTypes = renderer.value().getSupportedTypes();
// TODO: do something with 'supportedTypes'
}
return false;
}
}
注意: 如果您覆盖
getSupportedAnnotationTypes
,那么 return Set.of(Renderer.class.getName())
就可以实现。
package com.example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Renderer {
RendererType value() default RendererType.TEXT;
}
package com.example;
public enum RendererType {
TEXT(String.class),
TEXTAREA(String.class),
CHECKBOX(Boolean.class, boolean.class);
private final Class<?>[] supportedTypes;
// vararg parameter makes declaring the constants a little cleaner
RendererType(Class<?>... supportedTypes) {
this.supportedTypes = supportedTypes;
}
public Class<?>[] getSupportedTypes() {
// return a copy of the array to avoid modifications
return supportedTypes.clone();
}
}