1. 概述

在这篇文章中,我们将探讨Quarkus与经典Jakarta EE环境中的bean发现的区别。我们将重点关注如何确保Quarkus在外部模块中能够发现注解类。

2. 为何Quarkus需要索引

Quarkus的一个主要优势是其极快的启动时间。为了实现这一点,Quarkus将类路径注解扫描等步骤从运行时提前到了构建时。因此,我们需要在构建时声明所有依赖。

这意味着在运行环境中通过类路径扩展增强应用程序已不再可能。当在构建期间收集元数据时,索引就发挥作用了。索引意味着将元数据存储在一个索引文件中。这样,应用程序可以在启动时或需要时快速读取它。

让我们通过一个简单的示例来说明区别:

q1

Quarkus使用Jandex来创建和读取索引。

3. 创建索引

对于我们的Quarkus项目中的类,我们不需要做特别的事情——Quarkus Maven插件会自动生成索引。但我们需要关注依赖项,包括项目内部模块和外部库。

3.1. Jandex Maven插件

对于自定义模块,最直接的方法是使用Jandex Maven插件

<build>
    <plugins>
        <plugin>
            <!-- https://github.com/wildfly/jandex-maven-plugin -->
            <groupId>org.jboss.jandex</groupId>
            <artifactId>jandex-maven-plugin</artifactId>
            <version>1.2.1</version>
            <executions>
                <execution>
                    <id>make-index</id>
                    <goals>
                        <!-- phase is 'process-classes by default' -->
                        <goal>jandex</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

这个插件会在打包的JAR中生成一个META-INF/jandex.idx文件。当运行时提供该文件时,Quarkus会读取它。因此,每个包含此类文件的库都默认增强了索引。

对于Gradle构建,我们可以使用org.kordamp.gradle.jandex插件:

plugins {
    id 'org.kordamp.gradle.jandex' version '0.11.0'
}

3.2. 应用程序属性

如果我们无法修改依赖(例如外部库的情况下),我们需要在Quarkus项目的application.properties文件中显式指定它们:

quarkus.index-dependency.<name>.group-id=<groupId> quarkus.index-dependency.<name>.artifact-id=<artifactId> quarkus.index-dependency.<name>.classifier=(可选)

3.3. 框架规定的含义

如果不使用Jandex Maven插件,模块也可以包含一个META-INF/beans.xml文件。这实际上是被Quarkus采用并进行了一些调整的CDI技术的一部分,但我们不必仅限于使用CDI管理的bean。我们也可以声明例如JAX-RS资源,因为索引的范围是整个模块。

4. 总结

本文确定了Quarkus在运行时需要Jandex索引来检测注解类。索引在构建时生成,因此标准技术无法检测构建后添加到类路径中的注解类。

一如既往,所有的代码都可以在GitHub上找到,那里有一个包含Quarkus应用和一些提供CDI管理bean的多模块项目。