我正在考虑启动一个项目,用于使用注解生成Java代码(我不会详细介绍,因为这不是真正相关的)。我想知道该项目的有效性和有用性,让我印象深刻的是对注解处理器工具(apt)的依赖。
我想知道的是,因为我不能从经验中说出来,在Java中使用注解处理有什么缺点?
这些可以是任何内容,包括以下内容:
- 编写处理器时很难执行TDD
- 很难在构建系统上包含处理
- 处理需要很长时间,而且很难让它快速运行
- 在IDE中使用注解需要为每个注解提供插件,以使其在报告错误时具有相同的行为
这些只是例子,不是我的观点,我正在研究这些是否有任何一个是真的(包括问这个问题;- ))
我确信肯定有缺点(例如,Qi4J特别列出了不使用预处理器的优点),但我没有使用它的经验来告诉我它们是什么。
使用注解处理的唯一合理的替代方案可能是为相关IDE创建插件来生成代码(这有点类似于覆盖/实现方法特性,它将生成所有签名而不生成方法体)。然而,就我所知,每当代码的相关部分发生更改时,都必须重复该步骤,而注解处理不会。
关于这个例子中大量的注解,我不认为它的使用需要像这样,也许对于任何给定的类来说都是少数,当然,这不会阻止它被滥用。
3条答案
按热度按时间dgtucam11#
我创建了一组JavaBean注解来生成属性getter/setter、委托和接口提取(编辑:删除链接;不再支持)
测试它们可能会相当困难...
我通常通过在eclipse中创建一个包含测试代码的项目并构建它,然后进行复制并关闭注解处理来实现。
然后,我可以使用Eclipse将"活动"测试项目与项目的"预期"副本进行比较。
我还没有太多的测试用例(生成这么多的属性组合是非常乏味的),但这是有帮助的。
在构建系统中使用注解实际上非常简单,Gradle让这一点变得难以置信的简单,在eclipse中使用它只需要创建一个指定注解处理器扩展的插件,并在想要使用它的项目中打开注解处理。
我在一个持续构建环境中使用过注解处理,构建注解和处理器,然后在构建的其余部分使用它。
我还没有发现这是一个问题-小心你在处理器中做的事情。我在我的处理器中生成了很多代码,它运行得很好。在ant中它有点慢。
注意,Java6处理器可以运行得更快一些,因为它们是正常编译过程的一部分。然而,我在代码生成能力方面遇到了麻烦(我认为问题主要在于eclipse的支持和运行多阶段编译)。目前,我坚持使用Java5。
这是注解API中经过深思熟虑的事情之一。API有一个"messenger"对象来处理所有错误。每个IDE都提供了一个实现,它可以在代码中的正确位置将此转换为适当的错误消息。
我所做的唯一一件eclipse特有的事情是强制转换处理环境对象,这样我就可以检查它是作为构建运行还是用于编辑器协调。如果是编辑,我退出。最终我会将其更改为只在编辑时进行错误检查,这样它就可以在您键入时报告错误。不过要小心--您需要让它保持 * 真的 * 快,以便在协调期间使用,否则编辑会变得缓慢。
[根据评论添加更多内容]
注解处理器规范声明不允许修改包含注解的类,我怀疑这是为了简化处理(进一步的循环不需要包含注解的类,也防止了无限更新循环)
然而,您可以生成其他类,他们推荐这种方法。
我为所有的get/set方法和其他需要生成的方法生成了一个超类。我还让处理器验证带注解的类是否扩展了生成的类。例如:
我在同一个包中生成了一个类,其名称为带注解的类加上"Gen",并验证声明了带注解的类以扩展它。
我见过有人使用编译器树api来修改带注解的类--这是违反规范的,我怀疑他们会在某个时候堵住这个漏洞,这样它就不会工作了。
我建议生成一个超类。
我真的很喜欢使用注解处理器。设计得非常好,特别是IDE/命令行构建独立性。
现在,如果您正在进行代码生成,我建议您坚持使用Java5注解处理器-您需要运行一个名为apt的单独工具来处理它们,然后进行编译。
请注意,Java 5和Java 6注解处理器的API是不同的! Java 6处理API更好,恕我直言,但我只是还没有运气与Java 6处理器做我需要的。
当Java7发布时,我将再给新的处理方法一次机会。
如果您有任何问题,请随时给我发电子邮件。(scott@javadude.com)
希望这有帮助!
ttvkxqim2#
我认为如果注解处理器肯定会使用Java 6版本的API。这是将来会支持的API。Java 5 API仍然在非官方的com.sun.xyz名称空间中。
我认为在不久的将来我们会看到更多的注解处理器API的使用。例如Hibernate正在开发一个处理器,用于新的JPA 2查询相关的静态 meta模型功能。他们还在开发一个处理器,用于验证Bean Validation注解。因此注解处理将继续存在。
工具集成是可以的。主流IDE的最新版本包含配置注解处理器并将其集成到构建过程中的选项。主流构建工具也支持注解处理,但maven仍然会带来一些麻烦。
测试我发现了一个大问题。所有的测试都是间接的,并且以某种方式验证注解处理的最终结果。我不能编写任何简单的单元测试,这些测试只是Assert在TypeMirrors或其他基于反射的类上工作的简单方法。问题是不能在处理器编译周期之外示例化这些类型的类。我认为Sun在设计API时没有真正考虑到可测试性。
p4rjhz4m3#
有一个具体的问题可以帮助回答这个问题,那就是与什么相反?不做这个项目,还是不使用注解?如果不使用注解,还有什么选择?
就我个人而言,我发现过多的注解是不可读的,而且很多时候太不灵活了。请看一下Web服务上实现供应商所需WSDL的一个方法:
我发现这些代码非常难读,但是XML配置替代方案并不一定更好。