为什么 `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.RELEASE
和 3.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
的情况下,名称源自实际名称。
我发现一些关于 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.RELEASE
和 3.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
的情况下,名称源自实际名称。