java Java注解处理的弊端?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/687553/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:23:11  来源:igfitidea点击:

The drawbacks of annotation processing in Java?

java

提问by Grundlefleck

I am considering starting a project which is used to generate code in Java using annotations (I won't get into specifics, as it's not really relevant). I am wondering about the validity and usefulness of the project, and something that has struck me is the dependence on the Annontation Processor Tool (apt).

我正在考虑启动一个项目,该项目用于使用注释在 Java 中生成代码(我不会详细说明,因为它并不真正相关)。我想知道该项目的有效性和实用性,让我印象深刻的是对 Annontation Processor Tool (apt) 的依赖。

What I'd like to know, as I can't speak from experience, is what are the drawbacks of using annotation processing in Java?

我想知道的是,由于我无法从经验中说出,在 Java 中使用注释处理有什么缺点?

These could be anything, including the likes of:

这些可以是任何东西,包括:

  • it is hard to do TDD when writing the processor
  • it is difficult to include the processing on a build system
  • processing takes a long time, and it is very difficult to get it to run fast
  • using the annotations in an IDE requires a plugin for each, to get it to behave the same when reporting errors
  • 编写处理器时很难做TDD
  • 很难在构建系统中包含处理
  • 处理需要很长时间,并且很难让它快速运行
  • 在 IDE 中使用注释需要一个插件,以使其在报告错误时表现相同

These are just examples, not my opinion. I am in the process of researching if any of these are true (including asking this question ;-) )

这些只是例子,不是我的观点。我正在研究这些是否属实(包括问这个问题;-))

I am sure there must be drawbacks (for instance, Qi4Jspecifically list not using pre-processors as an advantage) but I don't have the experience with it to tell what they are.

我确信肯定有缺点(例如,Qi4J特别列出了不使用预处理器作为优势),但我没有经验来说明它们是什么。

The ony reasonable alternative to using annotation processing is probably to create plugins for the relevant IDEs to generate the code (it would be something vaguely similar to override/implement methods feature that would generate all the signatures without method bodies). However, that step would have to be repeated each time relevant parts of the code changes, annotation processing would not, as far as I can tell.

使用注释处理的任何合理替代方法可能是为相关 IDE 创建插件以生成代码(它与覆盖/实现方法功能模糊地相似,会生成没有方法主体的所有签名)。但是,每次代码的相关部分更改时都必须重复该步骤,据我所知,注释处理不会。

In regards to the example given with the invasive amount of annotations, I don't envision the use needing to be anything like that, maybe a handful for any given class. That wouldn't stop it being abused of course.

关于给出的带有侵入性注释数量的示例,我不认为使用需要像那样的东西,对于任何给定的类来说可能是少数。这当然不会阻止它被滥用。

回答by Scott Stanchfield

I've created a set of JavaBean annotations (http://code.google.com/p/javadude/wiki/Annotations)

我创建了一组 JavaBean 注释(http://code.google.com/p/javadude/wiki/Annotations

[Note: I'm working on a new version right now, so the trunk code doesn't match the update site downloads]

[注意:我现在正在开发一个新版本,所以中继代码与更新站点下载不匹配]

Testing

测试

Testing them can be quite trying...

测试它们可能会非常费力......

I usually approach it by creating a project in eclipse with the test code and building it, then make a copy and turn off annotation processing.

我通常通过在 eclipse 中使用测试代码创建一个项目并构建它来处理它,然后复制并关闭注释处理。

I can then use Eclipse to compare the "active" test project to the "expected" copy of the project.

然后我可以使用 Eclipse 将“活动”测试项目与项目的“预期”副本进行比较。

I don't have too many test cases yet (it's very tedious to generate so many combinations of attributes), but this is helping.

我还没有太多的测试用例(生成这么多的属性组合很乏味),但这很有帮助。

Build System

构建系统

Using annotations in a build system is actually very easy. Take a look at http://code.google.com/p/javadude/wiki/Annotationsfor an example of how it's used in an ant script, and using it in eclipse is just a matter of making a plugin specifying the annotation processor extension and turning on annotation processing in projects that want to use it.

在构建系统中使用注解实际上非常简单。看一下http://code.google.com/p/javadude/wiki/Annotations的一个例子,它是如何在 ant 脚本中使用的,在 eclipse 中使用它只是制作一个指定注释处理器的插件的问题扩展并在要使用它的项目中打开注释处理。

I've used annotation processing in a continuous build environment, building the annotations & processor, then using it in the rest of the build. It's really pretty painless.

我在连续构建环境中使用了注释处理,构建了注释和处理器,然后在构建的其余部分使用它。真的很无痛。

Processing Time

处理时间

I haven't found this to be an issue - be careful of what you do in the processors. I generate a lot of code in mine and it runs fine. It's a little slower in ant.

我没有发现这是一个问题 - 小心你在处理器中所做的事情。我在我的中生成了很多代码并且运行良好。在 ant 中它有点慢。

Note that Java6 processors can run a little faster because they are part of the normal compilation process. However, I've had trouble getting them to work properly in a code generation capacity (I think much of the problem is eclipse's support and running multiple-phase compiles). For now, I stick with Java 5.

请注意,Java6 处理器可以运行得更快一些,因为它们是正常编译过程的一部分。但是,我很难让它们在代码生成能力中正常工作(我认为大部分问题在于 eclipse 的支持和运行多阶段编译)。现在,我坚持使用 Java 5。

Error Processing

错误处理

This is one of the best-thought-through things in the annotation API. The API has a "messenger" object that handles all errors. Each IDE provides an implementation that converts this into appropriate error messages at the right location in the code.

这是注释 API 中最深思熟虑的事情之一。API 有一个处理所有错误的“信使”对象。每个 IDE 都提供了一个实现,可将其转换为代码中正确位置的适当错误消息。

The only eclipse-specific thing I did was to cast the processing environment object so I could check if it was bring run as a build or for editor reconciliation. If editing, I exit. Eventually I'll change this to just do error checking at edit time so it can report errors as you type. Be careful, though -- you need to keep it reallyfast for use during reconciliation or editing gets sluggish.

我所做的唯一特定于 Eclipse 的事情是强制转换处理环境对象,以便我可以检查它是作为构建运行还是用于编辑器协调。如果编辑,我退出。最终,我会将其更改为仅在编辑时进行错误检查,以便在您键入时报告错误。不过要小心——你需要保持它在协调或编辑变得缓慢期间使用非常快。

Code Generation Gotcha

代码生成陷阱

[added a little more per comments]

[每条评论多加一点]

The annotation processor specifications state that you are not allowed to modify the class that contains the annotation. I suspect this is to simplify the processing (further rounds do not need to include the annotated classes, preventing infinite update loops as well)

注释处理器规范声明您不得修改包含注释的类。我怀疑这是为了简化处理(进一步的回合不需要包含带注释的类,也可以防止无限更新循环)

You cangenerate other classes, however, and they recommend that approach.

但是,您可以生成其他类,他们推荐使用这种方法。

I generate a superclass for all of the get/set methods and anything else I need to generate. I also have the processor verify that the annotated class extends the generated class. For example:

我为所有 get/set 方法以及我需要生成的任何其他方法生成一个超类。我还让处理器验证带注释的类是否扩展了生成的类。例如:

@Bean(...)
public class Foo extends FooGen

I generate a class in the same package with the name of the annotated class plus "Gen" and verify that the annotated class is declared to extend it.

我在同一个包中生成了一个类,其中带有带注释的类的名称加上“Gen”,并验证是否声明了带注释的类来扩展它。

I have seen someone use the compiler tree api to modify the annotated class -- this is against spec and I suspect they'll plug that hole at some point so it won't work.

我见过有人使用编译器树 api 来修改带注释的类——这违反了规范,我怀疑他们会在某个时候堵塞那个漏洞,所以它不会工作。

I would recommend generating a superclass.

我建议生成一个超类。

Overall

全面的

I'm reallyhappy using annotation processors. Very well designed, especially looking at IDE/command-line build independence.

我真的高兴使用注释处理器。设计得很好,尤其是在 IDE/命令行构建独立性方面。

For now, I would recommend sticking with the Java5 annotation processors if you're doing code generation - you need to run a separate tool called apt to process them, then do the compilation.

现在,如果您要生成代码,我建议坚持使用 Java5 注释处理器 - 您需要运行一个名为 apt 的单独工具来处理它们,然后进行编译。

Note that the API for Java 5 and Java 6 annotation processors is different! The Java 6 processing API is better IMHO, but I just haven't had luck with java 6 processors doing what I need yet.

请注意,Java 5 和 Java 6 注释处理器的 API 是不同的!恕我直言,Java 6 处理 API 更好,但我还没有幸运地使用 Java 6 处理器做我需要的事情。

When Java 7 comes out I'll give the new processing approach another shot.

当 Java 7 出现时,我将再次尝试新的处理方法。

Feel free to email me if you have questions. ([email protected])

如果您有任何问题,请随时给我发电子邮件。([email protected])

Hope this helps!

希望这可以帮助!

回答by Hardy

I think if annotation processor then definitely use the Java 6 version of the API. That is the one which will be supported in the future. The Java 5 API was still in the in the non official com.sun.xyz namespace.

我认为如果注释处理器那么肯定使用 API 的 Java 6 版本。那就是将来会支持的那个。Java 5 API 仍然在非官方的 com.sun.xyz 命名空间中。

I think we will see a lot more uses of the annotation processor API in the near future. For example Hibernate is developing a processor for the new JPA 2 query related static meta model functionality. They are also developing a processor for validating Bean Validation annotations. So annotation processing is here to stay.

我认为在不久的将来我们会看到更多使用注解处理器 API 的情况。例如,Hibernate 正在为新的 JPA 2 查询相关的静态元模型功能开发处理器。他们还在开发用于验证 Bean Validation 注释的处理器。所以注释处理就在这里。

Tool integration is ok. The latest versions of the mainstream IDEs contain options to configure the annotation processors and integrate them into the build process. The main stream build tools also support annotation processing where maven can still cause some grief.

工具集成没问题。主流 IDE 的最新版本包含用于配置注释处理器并将它们集成到构建过程中的选项。主流构建工具还支持注释处理,而 maven 仍然会引起一些麻烦。

Testing I find a big problem though. All tests are indirect and somehow verify the end result of the annotation processing. I cannot write any simple unit tests which just assert simple methods working on TypeMirrors or other reflection based classes. The problem is that one cannot instantiate these type of classes outside the processors compilation cycle. I don't think that Sun had really testability in mind when designing the API.

测试我发现一个大问题。所有测试都是间接的,并以某种方式验证注释处理的最终结果。我无法编写任何简单的单元测试,这些测试只是断言在 TypeMirror 或其他基于反射的类上工作的简单方法。问题是不能在处理器编译周期之外实例化这些类型的类。我认为 Sun 在设计 API 时并没有真正考虑到可测试性。

回答by Yishai

One specific which would be helpful in answering the question would be as opposed to what? Not doing the project, or doing it not using annotations? And if not using annotations, what are the alternatives?

一个有助于回答问题的具体内容是什么?不做项目,或者不使用注释来做?如果不使用注释,有什么替代方法?

Personally, I find excessive annotations unreadable, and many times too inflexible. Take a look at this for one method on a web service to implement a vendor required WSDL:

就我个人而言,我发现过多的注释不可读,而且很多时候太不灵活了。看看这个 Web 服务上的一种方法来实现供应商要求的 WSDL:

    @WebMethod(action=QBWSBean.NS+"receiveResponseXML")
@WebResult(name="receiveResponseXML"+result,targetNamespace = QBWSBean.NS)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public int receiveResponseXML(
        @WebParam(name = "ticket",targetNamespace = QBWSBean.NS) String ticket,
        @WebParam(name = "response",targetNamespace = QBWSBean.NS) String response,
        @WebParam(name = "hresult",targetNamespace = QBWSBean.NS) String hresult,
        @WebParam(name = "message",targetNamespace = QBWSBean.NS) String message) {

I find that code highly unreadable. An XML configuration alternative isn't necessarily better, though.

我发现该代码非常不可读。不过,XML 配置替代方案不一定更好。