在运行时从注释处理器获取信息

Getting information from Annotation processor at runtime

我有一个工作的注释处理器,它收集带注释的 classes 的信息。编译期间一切都在那里。但我想在运行时访问这些结果。

@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {

    private final static List<TestInfo> tests = new ArrayList<>();

    @Override
    public Set getSupportedAnnotationTypes() {
        return new LinkedHashSet() {
            {
                add(Annotation.class.getCanonicalName());
            }
        };
    }

    @Override
    public boolean process(final Set<? extends TypeElement> annotations,
            final RoundEnvironment env) {
        System.out.println("Processing!");
        if (!env.processingOver()) {
            Set<? extends Element> rootE = env.getRootElements();
            for (Element e : rootE) {
                if (e.getKind() == ElementKind.CLASS) {
                    TestInfo t = new TestInfo(e.asType().toString());
                    for (Element se : e.getEnclosedElements()) {
                        if (se.getKind() == ElementKind.METHOD) {
                            t.addMethod(se.getSimpleName().toString());
                        }
                    }
                    getTests().add(t);
                }
            }
            getTests().forEach(ti -> {
                System.out.println(ti);
            });
        }
        return false;
    }

    public static TypeElement findEnclosingTypeElement(Element e) {

        while (e != null && !(e instanceof TypeElement)) {
            e = e.getEnclosingElement();
        }

        return TypeElement.class.cast(e);
    }

    /**
     * @return the tests
     */
    public static List<TestInfo> getTests() {
        return tests;
    }
}

有没有办法在运行时检索结果? TestProcessor.getTests returns 一个空列表。

这是测试信息 class 仅供参考:

public class TestInfo {

    private final String name;
    private final List<String> methods = new ArrayList<>();

    public TestInfo(String name) {
        this.name = name;
    }

    public void addMethod(String m) {
        getMethods().add(m);
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the methods
     */
    public List<String> getMethods() {
        return methods;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(name).append(methods.toString());
        return sb.toString();
    }
}

更新:注解标有保留运行时间。

查看 @RetentionPolicy。我认为您想将其设置为 RUNTIME

注释处理在编译时。所以你无法在运行时间内获取信息。

直接的方法是在编译时将信息写成资源文件,在运行时读取。

这是我的例子:

注解:

@Retention(SOURCE)
@Target(TYPE)
public @interface Anno {
}

处理器:

  @Override
  public boolean processActual(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    if (roundEnv.processingOver()) {
      return false;
    }
    try {
      write(roundEnv);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return false;
  }

  private void write(RoundEnvironment roundEnv) throws IOException, UnsupportedEncodingException {
    Filer filer = processingEnv.getFiler();
    FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", "TestInfo");
    OutputStream output = resource.openOutputStream();
    PrintStream writer = new PrintStream(output, false, "UTF-8");
    roundEnv.getElementsAnnotatedWith(Anno.class)
        .stream()
        .filter(e -> e.getKind() == ElementKind.CLASS)
        .map(e -> e.asType().toString())
        .forEach(writer::println);
    writer.flush();
  }

用户代码:

@Anno
public class Q48177784 {
  public static final List<Class<?>> CLASSES;
  static {
    try {
      URL resource = Q48177784.class.getClassLoader().getResource("TestInfo");
      CLASSES = Files.readAllLines(Paths.get(resource.toURI()))
          .stream()
          .map(s -> {
            try {
              return Class.forName(s);
            } catch (ClassNotFoundException e) {
              throw new Error(e);
            }
          })
          .collect(Collectors.toList());
    } catch (Exception e) {
      throw new Error(e);
    }
  }

  public static void main(String[] args) {
    System.out.println(CLASSES);
  }
}

使用处理器构建后,运行 main 方法:

[class xdean.Whosebug.Q48177784]

对于您的情况,您唯一应该做的就是 serialize/deserialize 您的 TestInfo