java 使用 Spring 通过构造函数自动装配集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3364283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 01:30:36  来源:igfitidea点击:

Autowiring a collection via the constructor with Spring

javaspringannotations

提问by Guillaume

I have what seems to be a simple problem, as stated in the title. Here is the kind of class I have :

正如标题中所述,我遇到了一个看似简单的问题。这是我的课程类型:

public class Foo {
    @Autowired
    public Foo(@Qualifier("bar") Set<String> bar) {
        // ...
    }
}

Which I try to run with the following spring context :

我尝试使用以下 spring 上下文运行:

<context:annotation-config />
<util:set id="bar">
    <value>tata</value>
    <value>titi</value>
    <value>toto</value>
</util:set>
<bean id="foo" class="Foo" />

This fails to run with :

这无法运行:

No matching bean of type [java.lang.String] found for dependency [collection of java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=bar)}

没有为依赖项 [java.lang.String 的集合] 找到类型为 [java.lang.String] 的匹配 bean:预期至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:{@org.springframework.beans.factory.annotation.Qualifier(value=bar)}

Note that if I add other parameters to my constructor, it works fine. If I use setter injection, it works fine. I'm sure I miss something obvious ... do you know what ?

请注意,如果我向构造函数添加其他参数,则它可以正常工作。如果我使用 setter 注入,它工作正常。我确定我错过了一些明显的东西......你知道吗?

回答by Christian Semrau

Autowiring collections is not possible using the @Autowiredannotation. An autowired collection means "to provide all beans of a particular type". Using the JSR-250 @Resourceannotation, you can declare that you want a resource injected by its name, not its type. Or you inject the dependency explicitly.

使用@Autowired注释无法自动装配集合。自动装配的集合意味着“提供特定类型的所有 bean”。使用 JSR-250@Resource注释,您可以声明您希望通过其名称而不是其类型注入资源。或者您显式注入依赖项。

[...] beans which are themselves defined as a collection or map type cannot be injected via @Autowiredsince type matching is not properly applicable to them. Use @Resourcefor such beans, referring to the specific collection/map bean by unique name.

[...] 本身定义为集合或映射类型的 bean 不能通过注入,@Autowired因为类型匹配不适用于它们。使用@Resource的唯一名称等豆类,指的是特定集合/图豆。

See the Spring documentationfor more details.

有关更多详细信息,请参阅Spring 文档

回答by mrembisz

As others stated it is impossible to use @Autowired for Strings and collections of String. You can use @Value with spring EL here assuming you have spring in version 3:

正如其他人所说,不可能将@Autowired 用于字符串和字符串集合。假设您在版本 3 中有 spring,您可以在此处将 @Value 与 spring EL 一起使用:

public class Foo {
    @Autowired
    public Foo(@Value("#{bar}") Set<String> bar) {
        // ...
    }
}

回答by entpnerd

I had this same problem and was inspired by @rembisz's answer. That answer didn't work on my version of Spring (4.1.3). When I checked the SpEL documentation on bean references, I found a different SpEL syntax to express bean references in autowired values that worked for me - @beanname. As such, the following code worked for me:

我遇到了同样的问题,并受到@rembisz 的回答的启发。该答案不适用于我的 Spring (4.1.3) 版本。当我检查有关 bean 引用SpEL 文档时,我发现了一种不同的 SpEL 语法来表达对我有用的自动装配值中的 bean 引用 - @beanname。因此,以下代码对我有用:

public class Foo {
    @Autowired
    public Foo(@Value("#{@bar}") Set<String> bar) {
        // ...
    }
}

回答by skaffman

I thinkthis is because Spring interprets the autowiring of a collection as "give me all beans of type String", rather than "give me the bean which is a collection of String". The error message supports that idea.

认为这是因为 Spring 将集合的自动装配解释为“给我所有类型的 bean String”,而不是“给我一个集合的 bean String”。错误消息支持这个想法。

I don't think you can use autowiring for this. Short of manually wiring it up in the XML, the best I can suggest is:

我认为您不能为此使用自动装配。没有在 XML 中手动连接它,我能建议的最好的方法是:

public class Foo {  
   private @Resource Set<String> bar;
}