是否可以从注释处理器内部获取与枚举关联的值?

问题描述 投票:0回答:1

在下面的情况下,我想获取

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;
  }
}
java enums annotations annotation-processing
1个回答
0
投票

如果您的注释处理器可以在编译时访问

Renderer
,那么最简单的方法是使用带有
AnnotatedConstruct#getAnnotation(Class)
的类文字。这将为您提供一个
Renderer
的实例,然后您可以像平常一样使用它。

示例

渲染处理器.java
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())
就可以实现。

渲染器.java
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;
}
渲染器类型.java
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();
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.