是否可以根据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

springboot初始化数据

3.springBoot+jpa

SpringBoot发送简单文本邮件

可以使用属性启用/禁用 Spring Boot @RestController 吗?

是否可以使用仪器从移动 safari 捕获站点的屏幕?