地图行为的 Spring 自动装配

Mar*_*ark 2 java spring dependency-injection

我的问题是关于 Spring 如何java.util.Map通过@Autowired. 具体来说,我看到的行为是类中自动装配的 bean 的值实际上是一个包含一个键值对的 Map,其中键是 bean 的名称,值是我打算注射。我预计 Spring 会直接注入地图。

这是我自动装配 bean 的类:

@Component
public class SpringMapParent {
    @Autowired
    @Qualifier("theMap")
    private Map<String, Object> theMap;

    ...
}
Run Code Online (Sandbox Code Playgroud)

theMap在 Spring Java 配置中定义如下:

@Configuration
@ComponentScan
public class SpringMapConfiguration {

    @Bean("theMap")
    public Map<String, Object> getTheMap() {
        Map<String, Object> theMap = new HashMap<String, Object>();
        return theMap;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,地图大小为 0。

我用于测试此注入的单元测试失败:

@ContextConfiguration(classes = {SpringMapConfiguration.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringMapIT {

    @Autowired
    private SpringMapParent springMapParent;

    @Test
    public void testSpringMapParentAutowiredCorrectly() {
        Map<String, Object> theMap = springMapParent.getTheMap();
        assertEquals(0, theMap.size());
    }
}
Run Code Online (Sandbox Code Playgroud)

的大小theMap实际上是 1。一个条目是:

{theMap={}}
Run Code Online (Sandbox Code Playgroud)

为什么是这样?以及如何将 bean 中定义的映射直接注入到theMap字段中?

Ken*_*kov 8

@AutowiredonMap是通过特定方式处理。文档说:

只要预期的键类型是字符串,即使是类型化的 Map 也可以自动装配。Map 值将包含预期类型的​​所有 bean,键将包含相应的 bean 名称

另一部分文档说:

对于本身定义为集合/映射或数组类型的 bean,这@Resource是一个很好的解决方案,通过唯一名称引用特定的集合或数组 bean。也就是说,从 4.3 开始,集合/映射和数组类型也可以通过 Spring 的@Autowired类型匹配算法进行匹配,只要元素类型信息保留在@Bean返回类型签名或集合继承层次结构中。在这种情况下,限定符值可用于在相同类型的集合中进行选择,如上一段所述。

因此,您可以通过以下方式注入Mapbean:

@Component
public class SpringMapParent {
    @Resource
    @Qualifier("theMap")
    private Map<String, Object> theMap;

    ...
}
Run Code Online (Sandbox Code Playgroud)