栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何通过AnnotationProcessor访问TypeUse注释

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何通过AnnotationProcessor访问TypeUse注释

TYPE_USE
注释是有点棘手,因为编译器将这些不同的,比“旧用法”的注释。

因此,正如您正确观察到的那样,它们不会传递给注释处理器,您的

process()
方法将永远不会收到它们。

那么如何在编译时使用它们呢?

在Java
8中,引入了这些注释,还引入了附加到Java编译的新方法。现在,您可以将侦听器附加到编译任务,并触发您自己对源代码的遍历。因此,访问批注的任务分为两部分。

  1. 钩到编译器
  2. 实施您的分析仪

广告1. Java
8中有2个选项可以挂接编译器。1.使用新的编译器插件API(https://docs.oracle.com/javase/8/docs/jdk/api/javac/tree/com/sun
/source/util/Plugin.html)2
.使用注释处理器

我没有太多使用选项#1,因为它需要明确地指定为javac参数。因此,我将介绍选项1:

您必须附加

TaskListener
到正确的编译阶段。有多个阶段。紧随其后的是唯一的一个,在此期间您具有可访问的语法树,该语法树表示包括方法主体在内的完整源代码(请记住,
TYPE_USE
即使在局部变量声明中也可以使用注释。

@SupportedSourceVersion(SourceVersion.RELEASE_8)public class EndProcessor extends AbstractProcessor {    @Override    public synchronized void init(ProcessingEnvironment env) {        super.init(env);        Trees trees = Trees.instance(env);        JavacTask.instance(env).addTaskListener(new TaskListener() { @Override public void started(TaskEvent taskEvent) {     // Nothing to do on task started event. } @Override public void finished(TaskEvent taskEvent) {     if(taskEvent.getKind() == ANALYZE) {         new MyTreeScanner(trees).scan(taskEvent.getCompilationUnit(), null);     } }        });    }    @Override    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {        // We don't care about this method, as it will never be invoked for our annotation.        return false;    }}

广告2。现在,他们

MyTreeScanner
可以扫描完整的源代码,并找到注释。无论您是否使用
Plugin
or
AnnotationProcessor
方法,都适用。这仍然很棘手。您必须实现
TreeScanner
或通常扩展
TreePathScanner
。这代表一种访客模式,您必须在其中进行适当的分析,以了解哪些元素是您感兴趣的。

让我们举一个简单的例子,它可以以某种方式对局部变量声明做出反应(给我5分钟):

class MyTreeScanner extends TreePathScanner<Void, Void> {    private final Trees trees;    public MyTreeScanner(Trees trees) {        this.trees = trees;    }    @Override    public Void visitVariable(VariableTree tree, Void aVoid) {        super.visitVariable(variableTree, aVoid);        // This method might be invoked in case of        //  1. method field definition        //  2. method parameter        //  3. local variable declaration        // Therefore you have to filter out somehow what you don't need.        if(tree.getKind() == Tree.Kind.VARIABLE) { Element variable = trees.getElement(trees.getPath(getCurrentPath().getCompilationUnit(), tree)); MyUseAnnotation annotation = variable.getAnnotation(MyUseAnnotation.class); // Here you have your annotation. // You can process it now.        }        return aVoid;    }}

这是非常简短的介绍。对于真实的示例,您可以查看以下项目源代码:https :
//github.com/c0stra/fluent-api-end-
check/tree/master/src/main/java/fluent/api/processors

在开发此类功能时进行良好的测试也非常重要,因此您可以调试,反向工程并解决您将在该领域遇到的所有棘手问题;)为此,您还可以从这里获得启发:
https://github.com/github.com。 com / c0stra / fluent-api-end-check / blob /
master / src / test / java / fluent / api /
EndProcessorTest.java

也许是我的最后一句话,因为javac确实对批注的使用有所不同,所以存在一些限制。例如,它不适合触发Java代码生成,因为编译器不会选择在此阶段创建的文件进行进一步编译。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/498342.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号