我正在考虑启动一个项目,该项目用于使用批注在Java中生成代码(我不会详细介绍,因为它并不重要)。我对项目的有效性和实用性感到好奇,令我震惊的是对Annontation Processor Tool(apt)的依赖。
我无法从经验中得知,我想知道的是在Java中使用注释处理的缺点是什么?
这些可以是任何东西,包括以下各项:
这些只是示例,不是我的看法。我正在研究其中任何一个是否正确(包括询问此问题;-))
我确信肯定有缺点(例如,Qi4J特别列出了不使用预处理器作为优势),但是我没有经验来告诉它们是什么。
使用注释处理的唯一合理选择可能是为相关的IDE创建插件来生成代码(这与覆盖/实现方法功能有些相似,后者将生成没有方法主体的所有签名)。但是,据我所知,每次代码的相关部分更改时,都必须重复执行该步骤,而注释处理则不会。
关于带有大量侵入性注释的示例,我不认为这种用法需要像这样,对于任何给定的类来说可能很少。当然,这不会阻止它被滥用。
我创建了一组JavaBean注释(http://code.google.com/p/javadude/wiki/Annotations)
[注意:我正在开发新版本,因此主干代码与更新站点下载不匹配]
测试中
测试它们可能是相当尝试的…
我通常通过在Eclipse中使用测试代码创建一个项目并构建它来进行处理,然后进行复制并关闭注释处理。
然后,我可以使用Eclipse将“活动”测试项目与项目的“预期”副本进行比较。
我还没有太多的测试用例(生成如此多的属性组合非常繁琐),但这很有帮助。
建立系统
实际上,在构建系统中使用注释非常容易。看一下http://code.google.com/p/javadude/wiki/Annotations上有关如何在ant脚本中使用它的示例,并在eclipse中使用它仅是制作一个指定注释处理器的插件的问题扩展并在要使用它的项目中打开注释处理。
我在连续的构建环境中使用了注释处理,构建了注释和处理器,然后在其余的构建中使用了注释和处理器。真的很轻松。
处理时间
我还没有发现这是一个问题-请谨慎对待处理器。我在我的代码中生成了很多代码,并且运行良好。蚂蚁有点慢。
请注意,由于Java6处理器是常规编译过程的一部分,因此它们可以运行得更快一些。但是,我很难让它们以代码生成的方式正常工作(我认为很多问题是eclipse的支持和运行多阶段编译)。现在,我坚持使用Java 5。
错误处理
这是注释API中经过深思熟虑的事情之一。API有一个处理所有错误的“信使”对象。每个IDE提供了一个实现,可以将其转换为代码中正确位置的相应错误消息。
我所做的唯一的蚀特定操作是强制转换处理环境对象,以便我可以检查该对象是否作为构建运行或用于编辑器对帐。如果进行编辑,则退出。最终,我将其更改为仅在编辑时执行错误检查,以便它可以在您键入时报告错误。不过请小心- 您需要在对帐过程中保持使用速度 非常 快,否则编辑速度会变慢。
代码生成陷阱
[每个评论增加了一点]
注释处理器规范指出,不允许您修改包含注释的类。我怀疑这是为了简化处理(进一步的回合不需要包含带注释的类,也可以防止无限的更新循环)
但是,您 可以 生成其他类,并且他们推荐这种方法。
我为所有get / set方法以及任何其他需要生成的东西生成一个超类。我还让处理器验证带注释的类是否扩展了生成的类。例如:
@Bean(...) public class Foo extends FooGen
我在同一包中生成一个类,并带有带注释的类的名称加上“ Gen”,并验证是否已声明带注释的类以对其进行扩展。
我见过有人使用编译器树api来修改带注释的类-这是违反规范的,我怀疑他们会在某个时候塞住该漏洞,因此将无法正常工作。
我建议生成一个超类。
总体
我真的 很 高兴使用注释处理器。设计得非常好,特别是考虑了IDE /命令行构建的独立性。
现在,如果您要进行代码生成,我建议使用Java5注释处理器-您需要运行一个名为apt的单独工具来处理它们,然后进行编译。
请注意,Java 5和Java 6注释处理器的API不同!Java 6处理API更好,恕我直言,但我还没有用Java 6处理器做我需要的运气。
当Java 7出现时,我将再次介绍新的处理方法。
如有疑问,请随时给我发送电子邮件。(scott@javadude.com)
希望这可以帮助!