热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

注释处理,RoundEnvironment.processingOver()

如何解决《注释处理,RoundEnvironment.processingOver()》经验,为你挑选了1个好方法。

在Java中读取自定义注释处理器的代码时,我注意到处理器process方法中的这段代码:

@Override
public boolean process(Set annotations, RoundEnvironment roundEnv) {
  if (!roundEnv.errorRaised() && !roundEnv.processingOver()) {
    processRound(annotations, roundEnv);
  }
  return false;
}

碰巧我正在使用自定义Annotation处理器,我想在我的注释处理器中使用上面的代码片段.

我用这种方式尝试了上面的代码:

if (!roundEnv.errorRaised() && !roundEnv.processingOver()) {
    processRound(annotations, roundEnv);
}
return false;

& 这条路:

if (!roundEnv.errorRaised()) {
    processRound(annotations, roundEnv);
}
return false;

但我没有注意到处理器行为的任何变化.我得到了!roundEnv.errorRaised()支票,但我看不出有!roundEnv.processingOver()什么用处.

我想知道roundEnv.processingOver()在处理某一轮时使用它的用例.



1> user1643723..:

这两项检查都很重要,但在同一项目中同时运行多个注释处理器之前,您不会注意到它们的影响.让我解释.

当Javac因任何原因(例如由于缺少类型声明或解析错误)而无法编译时,它不会立即终止.相反,它将尽可能多地收集有关错误的信息,并尝试以有意义的方式向用户显示该信息.此外,如果有注释处理器,并且错误是由缺少类型或方法声明引起的,Javac将尝试运行这些处理器并重试编译,希望它们生成缺少的代码.这称为"多轮编译".

编译序列如下所示:

    主轮(可能带代码生成);

    几个可选的代码生成轮; 新的回合将发生,直到注释处理器没有生成任何内容;

    最后一轮; 在这一轮中生成的代码不会受到注释处理.

每一轮都是编译代码的全面尝试.除最后一轮之外的每一轮将重新运行代码上的每个注释处理器,这些处理器先前由注释处理器生成.

这个奇妙的序列允许使用像Dagger2和Android-Annotated-SQL这样的库推广的方法:在源代码中引用一个尚未存在的类,并让注释处理器在编译期间生成它:

// this would fail with compilation error in absence of Dagger2
// but annotation processor will generate the Dagger_DependencyFactory
// class during compilation
Dagger_DependencyFactory.inject(this);

有些人认为这种技术是不合适的,因为它依赖于在源代码中使用不存在的类,并且将源代码与注释处理紧密联系起来(并且在IDE代码完成时不能很好地工作).但这种做法本身是合法的,并且按照Javac开发人员的意图运作.


那么,在你的问题中,所有这些与Spring的注释处理器有什么关系呢?

TL; DR:你问题中的代码是错误的.

使用这些方法的正确方法是这样的:

用于errorRaised:

    如果您的处理器生成新的公开可见类(可以像上面提到的那样"提前"使用用户代码),则必须具有超强弹性:继续生成,在可能的情况下忽略丢失的位和不一致,并忽略 errorRaised.这确保了在Javac进行错误报告狂欢时,您可以尽可能少地遗漏这些东西.

    如果你的代码没有生成新的公开可见类(例如,因为它只创建包私有类,而其他代码将在运行时反射性地查找它们,请参阅ButterKnife),那么你应该检查errorRaisedASAP,并立即退出返回true.这将简化您的代码并加速错误的编译.

用于processingOver:

    如果当前轮次不是最后一个(processingOver返回false),请尝试尽可能多地生成输出; 忽略用户代码中缺少的类型和方法(假设,其他一些注释处理器可能会在后续轮次中生成它们).但是仍然尽可能地生成,以防其他注释处理器可能需要它.例如,如果您在每个类上触发代码生成@Entity,您应该迭代这些类并尝试为每个类生成代码,即使以前的类有错误或缺少方法.就个人而言,我只是在try-catch中包装每个单独的生成单元,并检查processingOver:如果它是错误的,忽略错误并继续迭代注释并生成代码.这允许Javac通过运行它们直到完全满意来破坏由不同注释处理器生成的代码之间的循环依赖性.

    如果当前轮次不是最后一个(processingOver返回false),并且未处理前一轮注释中的一些注释(我记得它们因处理因异常而失败),则重试这些注释.

    如果当前回合是最后一个(processingOver返回true),请查看是否仍有未处理的注释.如果是这样,编译失败(仅在一轮!)

上面的顺序是预期的使用方式processingOver.

一些注释处理器使用processingOver的方式略有不同:它们缓冲每轮中生成的代码,并Filer在上一轮中实际写入.这允许解析对其他处理器的依赖性,但是阻止其他处理器找到由"仔细"处理器生成的代码.这是一个有点讨厌的策略,但如果生成的代码不打算在其他地方引用,我想这没关系.

并且有一些注释处理器,如上面提到的第三方Spring配置验证器:他们误解了一些东西,并以猴子和扳手的方式使用API​​.

为了更好地了解整个事物,请安装Dagger2,并尝试在类中引用Dagger生成的类,由另一个注释处理器使用(最好以某种方式使该处理器解析它们).这将很快向您展示这些处理器如何应对多轮编译.大多数人只会让Javac崩溃.有些人会吐出数千个错误,填充IDE错误报告缓冲区并混淆编译结果.很少有人能够正确参与多轮编译,但如果失败则仍会发出大量错误.

"尽管存在错误,仍保持生成代码"部分专门用于减少编译失败期间报告的编译错误的数量.减少缺少类=减少缺少声明错误(希望如此).或者,不要创建注释处理器,以煽动用户引用它们生成的代码.但是,当一些注释处理器生成代码时,您仍需要应对这种情况,并使用您的注释进行注释 - 与"提前"声明不同,用户希望这只是开箱即用.


回到原始问题:由于Spring配置验证处理器不会生成任何代码(希望,我没有深入研究它),但应该总是报告扫描配置中的所有错误,理想情况下应该这样工作:ignore errorRaised并推迟配置扫描,直到processingOver返回true:这将避免在多个编译轮次期间多次报告相同的错误,并允许注释处理器生成新的配置块.

遗憾的是,有问题的处理器看起来已经放弃了(自2015年以来没有提交过),但是作者在Github上很活跃,所以也许你可以向他们报告这个问题.

与此同时,我建议您从经过深思熟虑的注释处理器中学习,例如Google Auto,Dagger2或我的小型研究项目.


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
author-avatar
铲除飞网败类
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有