Quarkus如何加载多配置创建同一Java配置类的多个实例?
在Quarkus中批量映射多组配置为同一接口实例
问题背景
现有.properties配置文件内容如下:
test1.name=test1 test1.url=www.test.com test2.name=test2 test2.url=www.test2.com
当前通过创建多个继承自Generic的子接口并分别标注@ConfigMapping实现配置映射,但配置组数量较多时需创建大量重复接口,希望找到更简洁的实现方式。
解决方案1:使用@ConfigMapping集合映射(推荐)
Quarkus的@ConfigMapping支持直接将同前缀格式的配置映射为同类型实例的集合,无需定义多个子接口,有两种适配方式:
适配原有配置结构
直接基于现有配置格式定义顶层映射接口:
public interface Generic { String name(); String url(); } @ConfigMapping(prefix = "") // 根前缀匹配所有test*开头的配置项 public interface AllConfigs { // "test"会匹配test1、test2这类前缀,Map的key为1、2,对应值为Generic实例 Map<String, Generic> test(); }
优化配置结构(更推荐)
将配置调整为层级化格式,可读性更强:
tests.test1.name=test1 tests.test1.url=www.test.com tests.test2.name=test2 tests.test2.url=www.test2.com
对应接口定义:
public interface Generic { String name(); String url(); } @ConfigMapping(prefix = "tests") public interface AllConfigs { // Map的key为test1、test2,直接对应配置中的二级前缀 Map<String, Generic> test(); }
使用方式
注入AllConfigs即可获取所有实例:
@Inject AllConfigs allConfigs; // 获取单个实例 Generic test1 = allConfigs.test().get("test1"); Generic test2 = allConfigs.test().get("test2");
解决方案2:改进CDI生产者(避免重复代码)
如果不想调整配置结构,可通过CDI生产者结合循环逻辑批量生成实例,无需手动编写多个生产者方法:
public interface Generic { String name(); String url(); } @Dependent public class ConfigProducer { // 定义需要映射的配置前缀列表 private static final List<String> CONFIG_PREFIXES = List.of("test1", "test2"); @Produces @ApplicationScoped public Map<String, Generic> produceAllGenerics(Config config) { Map<String, Generic> instances = new HashMap<>(); for (String prefix : CONFIG_PREFIXES) { // 用Quarkus Config API直接构建Generic实例 Generic instance = config.getValue(prefix, Generic.class); instances.put(prefix, instance); } return instances; } }
使用方式
注入Map<String, Generic>直接通过key获取对应实例:
@Inject Map<String, Generic> genericMap; Generic test1 = genericMap.get("test1");
解决方案3:自定义配置读取(灵活度最高)
如果需要更精细的控制逻辑,可直接使用Quarkus的Config API手动读取配置并构建实例:
// 实现Generic接口的实体类 public class GenericImpl implements Generic { private final String name; private final String url; public GenericImpl(String name, String url) { this.name = name; this.url = url; } @Override public String name() { return name; } @Override public String url() { return url; } } @ApplicationScoped public class CustomConfigLoader { @Inject Config config; public Map<String, Generic> loadAllGenerics() { Map<String, Generic> instances = new HashMap<>(); // 遍历所有配置键,匹配test*前缀的配置项 for (Config.Key key : config.getPropertyNames()) { String keyStr = key.getName(); if (keyStr.startsWith("test") && keyStr.contains(".name")) { String prefix = keyStr.split("\\.")[0]; String name = config.getValue(prefix + ".name", String.class); String url = config.getValue(prefix + ".url", String.class); instances.put(prefix, new GenericImpl(name, url)); } } return instances; } }
使用方式
注入配置加载器并调用方法获取实例:
@Inject CustomConfigLoader configLoader; Map<String, Generic> genericMap = configLoader.loadAllGenerics(); Generic test1 = genericMap.get("test1");
内容的提问来源于stack exchange,提问作者0xRelu
相关产品推荐
相关产品推荐

