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

时间:2018-01-09 22:48:48

标签: java annotations runtime

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

@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返回一个空列表。

这是TestInfo类fyi:

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();
    }
}

更新:注释标记为保留运行时。

2 个答案:

答案 0 :(得分:1)

注释处理在编译时。因此,您无法在运行时获取信息。

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

以下是我的例子:

注释:

@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.stackoverflow.Q48177784]

对于您的情况,您应该做的唯一事情是序列化/反序列化您的TestInfo

答案 1 :(得分:0)

结帐RUNTIME。我想你想把它设置为String link = "https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=video&cd=1&cad=rja&uact=8&ved=0ahUKEwjNz9zuhczYAhWJoqQKHbGPDLMQFgglMAA&url=https%3A%2F%2Fwww.youtube.com%2Fchannel%2FUC-9-kyTW8ZkZNDHQJ6FgpwQ&usg=AOvVaw3k7TglV_ogkm4gsxKGAESI"; HttpURLConnection connection = (HttpURLConnection) (new URL(link).openConnection()); connection.connect();