Java,在编译时使用注释处理器索引注释类是一个很好的实践吗?

问题描述 投票:0回答:4

我正在考虑使用注释处理器在编译时为使用某种注释类型注释的类构建索引(甚至是存储在文件中的简单列表),以加快运行时带注释的类检索速度。

那么,这是一个好的做法吗?有什么缺点吗?如果它像我现在看起来的那样好,为什么没有很多库以简单的方式做到这一点(我找到的唯一一个是Class Index)?而不是运行时处理有这么多?

java annotations annotation-processing
4个回答
4
投票

作为 ClassIndex 库的作者,我可以列出使用注释处理进行注释索引的几个优点,但也列出了我认为阻碍其广泛采用的缺点。

优点:

  • 使用注释处理的索引基于官方 JSR 269。另一方面,类路径扫描依赖于 Java 内部。众所周知,类加载器没有 API 来检索带注释的类列表。但更令人惊讶的是,通用 ClassLoader 不允许列出它尝试加载类的文件夹和 JAR 文件。类路径扫描器假定用于加载类的唯一类加载器是 URLClassLoader,它允许使用 getURLs() 方法检索源 URL 进行扫描。
  • 在某些环境下,通常的类路径扫描器不起作用,在 Android 上使用 Dalvik 可执行文件格式就是这种情况。
  • 恒定的运行时复杂性使得编译时索引速度超级快。
  • Jigsaw 项目计划将 注释检测引入 Java。当前的要求还建议将编译时索引作为其可行的实现。它甚至引入了 @Indexed 元注释,其目的与 ClassIndex 库中的 @IndexAnnotated 相同。

缺点:

  • JSR 269 在 Java 编译器和工具中的支持很差。早期的 javac 版本中有几个错误。 Eclipse 的自定义 JDT 编译器有更多错误,并且它不支持注释处理器的自动发现。 ClassIndex 包含许多这些问题的解决方法。
  • 类路径扫描是事实标准,并且得到很好的支持。
  • 应用程序启动时间很少是需要担心的瓶颈。

2
投票

JBoss WildFly 的一个子项目,您可能会感兴趣:Jandex

它在构建时(并且索引文件可以添加到 JAR 中)或运行时(通过检查类文件而不是通过反射来检索注释)创建注释索引,显着提高注释检索的性能,因为它避免了实际加载类的需要.

Jandex 听起来很像你想要的。


1
投票

我认为主要缺点是比较复杂。注解处理是一个全新的 API 和概念,许多开发人员并不熟悉。 Reflection API 更简单,也更广为人知。您通常可以在运行时完成相同的任务。

如果更好的启动性能至关重要(这种情况很少发生),那么增加复杂性也许是值得的。

不过我不相信这些基准。他们声明“类路径大小设置为 121MB”——这是一个任意值,使得与硬编码或编译时处理的任何比较都完全无用。无论如何你为什么要扫描整个类路径?在大多数情况下,仅扫描开发人员类会更合理。

许多框架使用配置文件或具有API来限制需要扫描的类或包。这会显着增加启动时间。

为什么没有很多图书馆可以做到这一点

许多 OSGi 工具/框架都这样做。在编译时扫描注释,并将元数据写入 jar 清单文件,或者创建更复杂的元数据文件。我怀疑这样做的主要原因是为了保持与 bnd 和类似工具的兼容性,在注释或注释处理变得更流行之前,这些工具已被用于构建和编译 OSGi 组件的时间分析。此外,OSGi 组件有自己的生命周期,可以随时出现和消失。因此,在这种情况下,启动时间确实更重要,因为您不能只在应用程序启动时扫描一次。每当组件(重新)启动时,您都需要扫描注释。

我不会说这是一个好或坏的做法。当它适合您的需要时使用此技术。我会避免为了几毫秒的启动时间而增加太多的复杂性。


0
投票

SezPoz 使用注释处理器为此提供了一个固执己见且易于使用的界面。 Sławek 提到的注意事项适用。

© www.soinside.com 2019 - 2024. All rights reserved.