spring构造和自动线图如何映射

时间:2015-05-22 07:00:52

标签: java spring

我使用春天已经有一段时间但今天早上我遇到了一些意想不到的行为。 由于我无法自己决定这是一个期望的功能还是我在这里提出的错误,希望我能得到一些很好的解释,为什么会发生这种情况。

简而言之,我在应用程序上下文中定义了多个bean,并使用utils创建了两个map bean:map name space,只有部分bean添加到这些map中。这两个地图具有完全相同的条目。 然后我自动连接这些地图。一条自动线使用@Autowired注释完成,另一条使用@Resource

完成

令我惊讶的是,使用@Autowired注释的bean在上下文中获得了所有bean,而不仅仅是我在地图中专门放置的bean。使用@Resource注释自动连接的另一个只有预期的两个条目。

我主要对以下方面感兴趣: 1.为什么在我当时的上下文中声明的所有bean都出现在@Autowired地图而不是我添加的地图中 2.为什么@Resource@Autowired的行为方式不同

以下是重现上述场景的工作代码。

这里有一些界面:

package my.testing.pkg;

public interface Foo {
    void doStuff();
}

及其实施:

package my.testing.pkg;

public class FooImpl implements Foo {
    @Override
    public void doStuff() {}
}

spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:utils="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="foo_1" class="my.testing.pkg.FooImpl"/>
    <bean id="foo_2" class="my.testing.pkg.FooImpl"/>
    <bean id="foo_3" class="my.testing.pkg.FooImpl"/>
    <bean id="foo_4" class="my.testing.pkg.FooImpl"/>

    <utils:map id="fooMap1" map-class="java.util.HashMap">
        <entry key="foo_1" value-ref="foo_1"/>
        <entry key="foo_2" value-ref="foo_2"/>
    </utils:map>

    <utils:map id="fooMap2" map-class="java.util.HashMap">
        <entry key="foo_1" value-ref="foo_1"/>
        <entry key="foo_2" value-ref="foo_2"/>
    </utils:map>
</beans>

重现行为的测试用例:

package my.testing.pkg;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.util.Map;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/test-context.xml")
public class SpringMapCreatingTest {
    @Autowired
    private Map<String, Foo> fooMap1;
    @Resource
    private Map<String, Foo> fooMap2;

    @Test
    public void shouldInjectATwoEntriesMap() throws Exception {
        assertEquals("fooMap1 should have to entries", 2, fooMap1.size());
        assertEquals("fooMap2 map should have to entries", 2, fooMap1.size());
    }
}

提前感谢您的澄清。

3 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

检查spring docs,提示部分:

  

本身定义为集合或地图类型的bean不能   通过@Autowired注入,因为类型匹配不正确   适用于他们。将@Resource用于此类bean

所以最好使用@Resource而不是@Autowired for maps

答案 2 :(得分:0)

发生了以下情况:

  1. @Autowired依赖项将查找与其类型匹配的bean,在这种情况下,它将创建由其名称映射的bean Foo的映射。当你在bean列表上自动装配时会发生同样的行为,Spring将注入实现该接口的所有bean。
  2. @Resource依赖项将首先查找与依赖项名称匹配的bean,例如fooMap2并将其注入。