如何在QuarkusTestResourceLifecycleManager中注入Arc Bean及加载配置?
核心疑问
我尝试实现QuarkusTestResourceLifecycleManager,想在其中注入/查找Arc中的Bean,但始终失败。代码示例如下:
public class FlywayTestResource implements QuarkusTestResourceLifecycleManager { @Override public Map<String, String> start() { Flyway flyway = Arc.container().instance(Flyway.class).get(); // 此处执行失败 // ... } }
请问是不是根本无法在此处注入Bean?是不是因为此时Quarkus Arc还未初始化?
更新1:配置源异常
发现ConfigProvider.getConfig()的配置源中不包含application.properties。
更新2:临时方案的困扰
有一种“脏 hack”是把application.properties内容复制到系统属性,但我认为这种方式非常不雅。有没有更规范简便的方法将application.properties添加到配置源?临时方案代码如下:
public void loadApplicationProperties() { Properties properties = new Properties(); String path = this.getClass().getClassLoader().getResource("application.properties").getPath(); try (FileInputStream input = new FileInputStream(path)) { properties.load(input); for (String key : properties.stringPropertyNames()) { String value = properties.getProperty(key); System.setProperty(key, value); } System.out.println("Properties copied to environment variables successfully."); } catch (IOException e) { } }
关于Arc Bean无法获取的问题
是的,在QuarkusTestResourceLifecycleManager的start()方法中确实无法直接获取Arc容器中的Bean。原因在于Quarkus的测试启动流程里,QuarkusTestResourceLifecycleManager是在Arc容器初始化之前执行的——它的核心作用是为测试提前准备外部依赖(比如数据库、消息队列等),此时应用上下文还未启动,Arc容器自然也没有完成初始化,所以无法通过Arc.container()获取任何Bean实例。
如果你的场景是要在测试资源中使用Flyway执行数据库迁移,可以换两种思路:
- 手动初始化Flyway实例:不依赖Arc注入,直接通过读取配置(系统属性、环境变量或手动加载配置文件)获取数据库连接信息,自行构建Flyway对象。
- 使用官方Flyway扩展测试支持:Quarkus官方的Flyway扩展会自动在测试启动时执行迁移,无需自定义
QuarkusTestResourceLifecycleManager。
关于添加application.properties到配置源的问题
不推荐使用复制系统属性的“脏 hack”,Quarkus提供了更规范的方式:
方法1:用Quarkus Config API手动加载配置源
通过ConfigProviderResolver手动添加配置源,符合Quarkus配置体系,不会污染系统属性:
public void loadApplicationProperties() { try { URL resource = Thread.currentThread().getContextClassLoader().getResource("application.properties"); if (resource != null) { PropertiesConfigSource configSource = new PropertiesConfigSource( new File(resource.toURI()), "application.properties", ConfigSource.DEFAULT_ORDINAL ); ConfigProviderResolver.instance().getBuilder() .addSources(configSource) .build(); } } catch (URISyntaxException | IOException e) { // 处理异常逻辑 } }
方法2:利用TestResource返回配置映射
在QuarkusTestResourceLifecycleManager的start()方法中返回配置键值对,这些配置会被Quarkus配置系统优先加载,效果和读取application.properties一致,更符合组件设计初衷:
@Override public Map<String, String> start() { Map<String, String> testConfig = new HashMap<>(); // 示例:添加数据库连接、Flyway启动配置 testConfig.put("quarkus.datasource.jdbc.url", "jdbc:h2:mem:testdb"); testConfig.put("quarkus.flyway.migrate-at-start", "true"); return testConfig; }
内容的提问来源于stack exchange,提问作者syr

