【问题标题】:Injecting a Map<String, Double> using Spring Boot and application.yml使用 Spring Boot 和 application.yml 注入 Map<String, Double>
【发布时间】:2017-10-08 21:33:45
【问题描述】:

我知道,在 SO 中有很多类似的问题,但我无法使用它们摆脱这种情况。

我有一个 Spring Boot 应用程序。

@SpringBootApplication
@EnableConfigurationProperties
public class Application implements ApplicationRunner {
    public static void main(String[] args) {
        SpringApplication.run(Application .class, args);
    }
}

那我有下面的课。

@Component
@ConfigurationProperties(prefix = "somePrefix")
public class AClass {
    private final AnotherClass anotherClass;
    private final Map<String, Double> aMap;

    @Autowired
    public AffinityChecks(AnotherClass anotherClass,
                          Map<String, Double> aMap) {
        this.anotherClass = anotherClass;
        this.aMap = aMap;
    }

    // Omissis

最后我有了下面application.yml的配置文件。

somePrefix:
  aMap:
    key1: 0.6
    key2: 0.2
    key3: 0.2

我想要的只是 Spring 在构建过程中将地图注入类型为AClass 的对象中。我得到的错误如下。

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Map<java.lang.String, java.lang.Double>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

这到底是怎么回事?

提前致谢。

【问题讨论】:

  • 尝试从构造函数中删除“Map aMap”。 docs.spring.io/spring-boot/docs/current/reference/html/…
  • 如果我从构造函数中删除地图,错误就会消失,因为 aMap 不再被 Spring 初始化;)
  • 您可能需要为您的地图添加 getter
  • 阅读文档应该会有所帮助:docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… - 我们不支持构造函数注入,您的属性必须是 javabean 属性(因此除了映射和嵌套之外,getter 和 setter 即非标量,只需要 getter 的值)。
  • @StephaneNic​​oll 你是对的。这解决了我的问题。如果你想回答这个问题,我会接受。谢谢

标签: java spring spring-boot properties


【解决方案1】:

Spring Boot 不支持对绑定到环境的元素进行构造函数注入。您当然可以按通常的方式注入实际的 bean。

您需要将要绑定的每个属性定义为常规 Javabean 属性(即使用 getter/setter)。此规则有一个例外:映射和非标量值(即嵌套内容)只需要一个 getter。

具体来说,如果 AnotherClass 是一个 bean 并且 FooClass 是一些具有嵌套属性的 pojo。

@Component
@ConfigurationProperties(prefix = "somePrefix")
public class AClass {
    private final AnotherClass anotherClass;
    private final Map<String, Double> aMap = new HashMap<>();
    private final FooClass foo = new FooClass();

    public AClass(AnotherClass anotherClass) { ...}

    public Map<String, Double> getaMap() { ... }

    public FooClass getFoo() { ... }

}

(请注意,getter 是推断属性名称的东西。在上面的示例中,如果您在FooClass 上有一个getXyz(),则可以映射somePrefix.foo.xyz)。

有一个示例in the documentation 包含更多详细信息。

(您的代码错误的一个很好的提示是地图不是 bean,因此 @Autowiring 不是您想要实现的正确语义)。

【讨论】:

  • AnotherClass 是一个豆子。事实上,我不太喜欢在这种情况下不使用构造函数注入:(
  • 你可以注入另一个类。没问题。我们不支持为要绑定的事物注入构造函数。我已经更新了我的答案。
  • 这正是我所做的。谢谢。但是我认为最好的解决方案是将所有从配置文件中读取的值封装在一个专用对象中(而不是业务类型AClass)
  • 嗯,这是你的代码,我提供了一个你给我的例子。我不认为在配置属性中注入协作者是个好主意。
猜你喜欢
  • 2014-12-22
  • 2014-09-15
  • 1970-01-01
  • 2020-03-24
  • 2018-01-04
  • 2019-05-09
  • 2017-04-04
  • 2014-08-15
  • 2011-08-31
相关资源
最近更新 更多