能否在依赖中定义Quarkus的@QuarkusMain方法并正常生效?
我用Quarkus构建一款SDK,核心需求有两个:
- SDK提供对接第三方系统的高层级API;
- 支持基于该SDK构建原生镜像(native image)。
直接在项目里使用Quarkus时,这两个功能都能正常运行。但将Quarkus作为传递依赖使用时出现了问题,项目结构如下:
test-sdk:提供API的SDK本身,内部用@QuarkusMain标记了主类,主类包含预期的标准输出日志逻辑;test-parent:支持构建原生镜像的父POM;test-project:依赖test-parent和test-sdk的项目,期望该项目无需感知Quarkus的存在。
在test-project中执行mvn clean package -Dnative命令可成功构建原生镜像,但运行该镜像时,看不到test-sdk主类中预期的日志输出。将所有内容整合到单个项目时则能正常输出,推测是依赖中定义的@QuarkusMain未生效。
我的疑问:我的预期是否有误?有没有可行的实现方案?
你的预期完全合理,确实可以实现Quarkus SDK作为传递依赖且支持原生镜像构建的需求,问题出在Quarkus原生镜像构建机制对传递依赖中@QuarkusMain的默认处理逻辑上,以下是具体原因和解决办法:
原因分析
Quarkus构建原生镜像时,默认仅扫描当前项目的源码和类路径来识别@QuarkusMain类,不会主动扫描传递依赖中的@QuarkusMain。当test-project作为独立项目构建时,Quarkus未自动将依赖中的@QuarkusMain注册为应用入口,导致运行原生镜像时未执行SDK主类的逻辑。
可行方案
方案1:在test-project中显式指定主类
无需修改代码,仅通过配置间接指定主类即可满足“不感知Quarkus”的预期:
在test-project的src/main/resources/application.properties中添加配置:
quarkus.main.class=org.example.Main
原生镜像构建时会明确以SDK中的主类作为入口,运行时即可执行对应的日志输出逻辑。
方案2:在test-sdk中通过Quarkus扩展自动注册主类
如果不想让test-project做任何配置修改,可在test-sdk中编写Quarkus扩展,自动触发主类执行:
- 创建扩展类:
import io.quarkus.runtime.annotations.QuarkusExtension; import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.Quarkus; @QuarkusExtension @RegisterForReflection public class SdkMainExtension { static { Quarkus.run(org.example.Main.class); } }
- 在
test-sdk的META-INF/services/io.quarkus.runtime.annotations.QuarkusExtension文件中添加扩展类全限定名:
org.example.SdkMainExtension
当test-project依赖test-sdk时,Quarkus扩展会自动触发主类执行,无需test-project做额外配置。
方案3:通过test-parent统一配置主类
在test-parent的POM中,修改Quarkus原生镜像构建插件配置,明确指定主类:
<plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-maven-plugin</artifactId> <version>${quarkus.version}</version> <executions> <execution> <goals> <goal>build</goal> </goals> <configuration> <mainClass>org.example.Main</mainClass> </configuration> </execution> </executions> </plugin>
test-project继承父POM后,会自动使用SDK中的主类构建原生镜像。
验证建议
构建原生镜像后运行时,可添加-Dquarkus.log.level=DEBUG参数查看日志,确认Quarkus是否正确加载了SDK中的主类。
内容的提问来源于stack exchange,提问作者Haris Osmanagić

