为什么 `autowire=byType` 也会按名称注入 bean?

Why `autowire=byType` will also inject beans by name?

我发现一些关于 autowire=byType 行为的不清楚之处。

Java包下的代码my:

public class User {
    private String name;
    public User(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserService {

    @Autowired
    private User user1;
    @Autowired
    private User user2;

    public String getNames() {
        return user1.getName() + " & " + user2.getName();
    }

}

Spring 配置:

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

    <context:component-scan base-package="my"/>

    <context:annotation-config/>

    <bean id="user1" class="my.User" autowire="byType">
        <constructor-arg value="Freewind"/>
    </bean>

    <bean id="user2" class="my.User" autowire="byType">
        <constructor-arg value="Lily"/>
    </bean>

</beans>

运行代码:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService service = context.getBean(UserService.class);
        System.out.println(service.getNames());
    }
}

运行良好并打印:

Freewind & Lily

但我预料它应该不起作用,因为我在定义bean时使用了autowire="byType",并且UserService中有两个相同类型User的bean。

而且,如果我更改了 bean 的名称,比如 user1 -> user999,它会报告一些错误,例如 No qualifying bean of type [my.User] is defined 错误。

即使我指定了byType,似乎spring也会自动检查名称,这很奇怪。

PS:我用 spring 4.1.3.RELEASE3.2.2.RELEASE 进行了测试,行为相同。

<bean id="user2" class="my.User" autowire="byType">
    <constructor-arg value="Lily"/>
</bean>

这里的 autowire="byType" 意味着你想要将(缺失的)依赖项注入到这个 bean byType 中。它仅适用于属性所在的 bean。在 xml 命名空间中,可以设置所有 bean 的默认值。

但是在您的情况下,您实际使用的是注释(注意 <context:annotation-config /> 已经暗示了 </context:component-scan /> 的用法)。注释驱动注入(@Autowired@Inject 总是按类型,@Resource 使用名称或 jndi 查找并按名称作为回退)。

当启动应用程序并为每个所需的依赖项扫描组件时,将创建 DependencyDescriptor。 class 包含用于自动装配的详细信息,其中包括类型和名称。在 Field 的情况下,名称源自实际名称。