是否可以根据springboot中application.properties中的前缀创建多个bean
Posted
技术标签:
【中文标题】是否可以根据springboot中application.properties中的前缀创建多个bean【英文标题】:Is it possible to create multiple beans depending on prefix in application.properties in springboot 【发布时间】:2018-08-17 11:44:51 【问题描述】:我的 springboot 应用程序 (1.5.4.RELEASE) 中的 application.properties 中有以下内容
my.prefix.one.id=id01
my.prefix.one.name=one
my.prefix.two.id=id02
my.prefix.two.name=two
还有一个像下面这样的类
public class MyClass
private String id;
private String name;
//getters and setters
如果我使用 @ConfigurationProperties(prefix="my.prefix.one") 那么我会得到一个带有 id 字段“id01”的 MyClass bean。
有没有办法指示springboot扫描扫描所有带有前缀“my.prefix”的属性并创建多个bean。在这种情况下,两个 bean - id 字段为“id01”的 bean 和 id 字段为“id02”的 bean?
【问题讨论】:
【参考方案1】:您应该使用弹簧@ConfigurationProperties
并在您的MyClass
中使用嵌套类
@ConfigurationProperties(prefix="my.prefix")
public class MyClass
private One id01;
private Two id02;
//GETTER SETTER
public static class One
private String id;
// GETTER SETTER
public static class Two
private String id;
// GETTER SETTER
然后你就可以像访问它了
myClass.getOne().getId();
最好的办法是通读https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties
更新:OP 不想使用嵌套类来检索这些字段
@ConfigurationProperties(prefix="my.prefix")
public class MyClass
private String id01;
private String id02;
@NotNull
private One one;
@NotNull
private Two two;
public getId01()
return one.id;
public getId02()
return two.id;
public static class One
private String id;
// GETTER SETTER
public static class Two
private String id;
// GETTER SETTER
现在你可以像这样使用它们了
myClass.getId01();
myClass.getId02();
【讨论】:
但我不想创建两个类定义 MyClass.One 和 MyClass.Two。它们都具有相同的结构 具有相同的结构应该不是问题。我已经修改了 myClass 吸气剂以符合您的要求。希望你想这样使用它。你是吗? 他不关心它们是否具有相同的结构,他不想为每个实例创建一个类。 @pavankumar 我仍在等待 OP 通过回答我的问题来确认。 @Amit,您对我刚刚提出的答案有何看法?即,使用多个配置方法而不是多个嵌套类。【参考方案2】:我已经尝试过类似的操作,据我所知,创建多个实例的唯一方法是获取具有指定前缀的 all 属性并自己解析它们。对于您的示例,您可以像这样构造一个@Configuration
:
@Configuration
public class MyConfig
@Bean
@ConfigurationProperties(prefix = "my.prefix")
protected Map<String, String> myProperties()
return new HashMap<>();
@Bean
public List<MyClass> myObjects(@Qualifier("myProperties") final Map<String, String> myProperties)
final Map<String, Map<String, String>> mappedSources = new HashMap<>();
myProperties.forEach((key1, value) ->
final String[] key = key1.split("\\.");
final Map<String, String> myInstanceParams = mappedSources.computeIfAbsent(key[0], s -> new HashMap<>(2));
myInstanceParams.put(key[1], value);
);
return mappedSources.values().stream()
.map(stringStringMap -> new MyClass(stringStringMap.get("id"), stringStringMap.get("name")))
.collect(Collectors.toList());
在这个简单的例子中,@Qualifier
不需要在 myObjects()
参数列表中,但是如果你在想要做类似的地方引入第二个前缀,那么你需要限定将哪个字符串映射传递到 @987654325 @ 方法,所以我建议从一开始就包含它。
这是一个简单的例子,但更健壮的实现会检查缺失的属性和属性有效性等。我也不能说这个解决方案是否是好的实践/好的 Spring 实践。
【讨论】:
【参考方案3】:由于你使用的是springboot,你也可以这样做:
@Configuration
public class AppBeanConfig
@Bean
@ConfigurationProperties(prefix="my.prefix.one")
public MyClass myClassOne()
return new MyClass();
@Bean
@ConfigurationProperties(prefix="my.prefix.two")
public MyClass myClassTwo()
return new MyClass();
我不知道有什么有意义的方法可以避免配置单个 bean。
但是,如果您真的想要这样做,您可以访问 ApplicationContext 并手动处理属性并将 bean 注入 Applicationcontext,我个人更喜欢将多个 bean 方法添加到配置类而不是直接操作 ApplicationContext。
【讨论】:
上述解决方案有什么问题?你能给我推荐一个更简单的解决方案吗?我认为在父级中拥有内部战略类和两个实例并不比拥有两个 break 方法更好。【参考方案4】:如果一、二的属性相同,只需使用同一个类即可。 Lombok 可帮助您自动创建 getter/setter 方法,这是使其正常工作所必需的
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix="my.prefix")
public class MyClass
private Child one;
private Child two;
@Getter
@Setter
public static class Child
@NotNull
private String id;
@NotNull
private String name;
【讨论】:
您可以创建两个带有正确注释的海滩方法的bean,而不是创建嵌套的静态类。以上是关于是否可以根据springboot中application.properties中的前缀创建多个bean的主要内容,如果未能解决你的问题,请参考以下文章
根据环境变量设置 Spring Boot application.properties