简体   繁体   English

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

[英]Java, Is index annotated classes at compile time with Annotation Processor a good practice?

I am thinking about building an index (even a simple list stored in a file) of classes annotated with a certain annotation type at compile time with an annotation Processor in order to speed up annotated class retrieval at runtime. 我正在考虑在编译时使用注释处理器构建一个使用某种注释类型注释的类的索引(甚至是存储在文件中的简单列表),以便在运行时加速注释类检索。

So, is it a good practice? 那么,这是一个好习惯吗? Are there any drawbacks? 有什么缺点吗? If it is as good as it seems to me now, why aren't there many libraries to do this in an easy way (the only one I have found is Class Index )? 如果它现在看起来和我一样好,为什么没有很多库以简单的方式做到这一点(我发现的唯一一个是Class Index )? Instead for runtime processing there are so many? 而不是运行时处理有那么多?

As an author of the ClassIndex library I can list several advantages of using annotation processing for annotation indexing, but also a drawbacks which I think hinder its widespread adoption. 作为ClassIndex库的作者,我可以列出使用注释处理进行注释索引的几个优点,但也有一些缺点,我认为这会阻碍其广泛采用。

Advantages: 好处:

  • Indexing using annotation processing is based on the official JSR 269. On the other hand the classpath scanning relies on Java internals. 使用注释处理进行索引是基于官方JSR 269.另一方面,类路径扫描依赖于Java内部。 It is a common knowledge that ClassLoaders do not have an API to retrieve a list of annotated classes. 众所周知,ClassLoader没有API来检索带注释的类的列表。 But what is more surprising is that the generic ClassLoader does not allow to list folders and JAR files from where it tries to load the classes. 但更令人惊讶的是,泛型ClassLoader不允许从尝试加载类的位置列出文件夹和JAR文件。 Classpath scanners assume the only classloader used to load classes is URLClassLoader which allows to retrieve source URLs for scanning using getURLs() method . 类路径扫描程序假设用于加载类的唯一类加载器是URLClassLoader,它允许使用getURLs()方法检索源URL以进行扫描。
  • There are environments where usual classpath scanners do not work , that is the case on Android where Dalvik Executable format is used. 在通常的类路径扫描程序不起作用的环境中,在使用Dalvik可执行文件格式的Android上就是这种情况。
  • Constant run-time complexity makes compile-time indexing super fast. 恒定的运行时复杂性使编译时索引超快。
  • Project Jigsaw plans to bring annotation detection to Java . Project Jigsaw计划将注释检测引入Java Current requirements also suggest a compile-time indexing as a viable implementation for it. 当前的要求还建议将编译时索引作为其可行的实现。 It even introduces @Indexed meta-annotation with the same purpose as @IndexAnnotated in ClassIndex library. 它甚至还介绍@Indexed元注释有异曲同工之妙的@IndexAnnotated在ClassIndex库。

Drawbacks: 缺点:

  • JSR 269 is poorly supported across Java compilers and tools. JSR 269在Java编译器和工具中得不到很好的支持。 There were several bugs in the earlier javac versions. 早期的javac版本中有几个错误。 Eclipse's custom JDT compiler has even more bugs and it does not support automatic discovery of annotation processors. Eclipse的自定义JDT编译器有更多错误,它不支持自动发现注释处理器。 ClassIndex includes workarounds for many of those issues. ClassIndex包含许多这些问题的解决方法。
  • Classpath scanning is the facto standard and is very well supported. 类路径扫描是事实上的标准,并且得到了很好的支持。
  • Application boot time is rarely a bottleneck to worry about. 应用程序启动时间很少是担心的瓶颈。

I think the main disadvantages is that it's more complicated. 我认为主要的缺点是它更复杂。 Annotation processing is a whole new API and concept that many developers aren't familiar with. 注释处理是许多开发人员不熟悉的全新API和概念。 The Reflection API is easier and more well known. Reflection API更容易且更为人所知。 You can usually accomplish the same tasks at runtime. 您通常可以在运行时完成相同的任务。

If better startup performance is crucial (which is rarely the case) then maybe it's worth the added complexity. 如果更好的启动性能是至关重要的(这种情况很少见),那么可能值得增加复杂性。

I wouldn't trust the benchmarks though. 我不相信基准。 They state "classpath size was set to 121MB" - an arbitrary value that makes any comparison to hard coded or compile time processing completely useless. 他们声明“类路径大小设置为121MB” - 一个任意值,使任何比较硬编码或编译时处理完全无用。 Why would you want to scan the whole class path anyway? 你为什么要扫描整个类路径呢? Scanning only the developers classes would be more reasonable in most cases. 在大多数情况下,仅扫描开发人员类会更合理。

Many frameworks use configuration files or have an API to limit the classes or packages that need to be scanned. 许多框架使用配置文件或使用API​​来限制需要扫描的类或包。 This increases startup time significantly. 这显着增加了启动时间。

why aren't there many libraries to do this 为什么没有很多图书馆可以做到这一点

Many OSGi tools/frameworks do this. 许多OSGi工具/框架都是这样做的。 Annotations are scanned at compile time and meta-data is written to the jar manifest file or they create more sophisticated meta-data files. 在编译时扫描注释,并将元数据写入jar清单文件,或者创建更复杂的元数据文件。 I suspect the main reason for this is to keep compatibility with bnd and similar tools, which have been used to built and compile time analysis of OSGi components before annotations or annotation processing got more popular. 我怀疑这样做的主要原因是为了保持与bnd和类似工具的兼容性,这些工具在注释或注释处理变得越来越流行之前用于构建和编译OSGi组件的时间分析。 Also, OSGi component have their own lifecycle and can come and go at any time. 此外,OSGi组件有自己的生命周期,可以随时进出。 So this is a case where startup time does matter a bit more, as you can't only scan once at application start. 因此,这是一个启动时间确实重要的情况,因为您不仅可以在应用程序启动时扫描一次。 You would need to scan for annotations whenever a component (re-)starts. 每当组件(重新)启动时,您都需要扫描注释。

I wouldn't say it's a good nor bad practice. 我不会说这是一个好的也不是坏的做法。 Use this technique when it fits your needs. 在满足您的需求时使用此技术。 I would avoid adding to much complexity for the sake of a few milliseconds startup time. 为了几毫秒的启动时间,我会避免增加复杂性。

A sub-project of JBoss WildFly, may be interesting to you: Jandex . JBoss WildFly的子项目可能对你很有意思: Jandex

It creates annotation indexes at build time (and index file can be added to the JAR) or runtime (annotations are retrieved by examining class files, not through reflection), significantly increasing performance of annotation retrieval as it avoids the need to actually load classes. 它在构建时创建注释索引(并且可以将索引文件添加到JAR)或运行时(通过检查类文件而不是通过反射来检索注释),从而显着提高注释检索的性能,因为它避免了实际加载类的需要。

Jandex sounds pretty much like what you are after. Jandex听起来非常像你所追求的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java 注释处理器 - 带注释的 Kotlin 类单元测试 - Java annotation processor - Annotated Kotlin classes unit tests Java注释处理器是否能够删除注释的代码 - Is Java annotation processor capable of removing annotated code Java / Kotlin注释处理器:获取带注释的字段/属性的类型 - Java/Kotlin annotation processor: get type of annotated field/property 使用Java注释处理器查找带注释方法的方法参数? - Find Method Arguments of annotated Method using Java Annotation Processor? 如何只允许在 Java 中的方法参数中使用某些注释进行注释的类? - How to allow only classes annotated with some annotation in method parameters in Java? Gradle - 在编译期间执行自定义注释处理器 - Gradle - Executing custom annotation processor during compile time 在编译期间使用注释处理器扩展类功能 - Extend class functionality with annotation processor during compile time 如何确定注释处理器中被注释元素的类路径? - How to determine the classpath of an annotated element in an annotation processor? 过滤带有特定注释的类 - Filter classes that are annotated with a specifi annotation 如何将 Schematron 编译成带有 Jaxb 注释的 Java 类? - How can I compile Schematron into Jaxb annotated Java classes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM