Java,在编译时使用Annotation Processor进行索引注释类是一种很好的做法吗?

时间:2015-01-24 19:23:06

标签: java annotations annotation-processing

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

那么,这是一个好习惯吗?有什么缺点吗?如果它现在看起来和我一样好,为什么没有很多图书馆能够以一种简单的方式做到这一点(我发现的唯一一个是Class Index)?而不是运行时处理有那么多?

3 个答案:

答案 0 :(得分:2)

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

优点:

  • 使用注释处理进行索引是基于官方JSR 269.另一方面,类路径扫描依赖于Java内部。众所周知,ClassLoader没有API来检索带注释的类的列表。但更令人惊讶的是,泛型ClassLoader不允许从尝试加载类的位置列出文件夹和JAR文件。类路径扫描程序假设用于加载类的唯一类加载器是URLClassLoader,它允许使用getURLs() method检索要扫描的源URL。
  • 在通常的类路径扫描程序do not work的环境中,在Android上使用Dalvik可执行文件格式的情况。
  • 持续的运行时复杂性使编译时索引超快。
  • Project Jigsaw计划带来annotation detection to Java。当前的要求还建议将编译时索引作为其可行的实现。它甚至在ClassIndex库中引入@Indexed元注释与@IndexAnnotated的目的相同。

缺点:

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

答案 1 :(得分:1)

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

如果更好的启动性能至关重要(这种情况很少发生),那么它可能会增加复杂性。

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

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

  

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

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

我不会说这是一个好的或不好的做法。在满足您的需求时使用此技术。为了几毫秒的启动时间,我会避免增加复杂性。

答案 2 :(得分:1)

JBoss WildFly的子项目可能会让您感兴趣:Jandex

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

Jandex听起来非常像你所追求的。