为什么Spring在自动装配时自动选择超类类型?
例如,如果我有
@Component
public class Foo {}
@Component
public class Bar extends Foo {}
有人自动接线
@Autowired
private Foo foo;
Spring 为什么总是选择超类型
Foo
?这不应该是一个“ambiguously”映射(并导致 Spring 抛出错误)吗?
从技术上讲,您没有两个
Foo
候选人吗? (例如,当从 Foo 中删除 @Component 时,Bar 会被自动选取...)
这可能是因为自动装配是通过名称而不是类型完成的。如果我像这样使用 xml 设置我的 bean:
<bean id="foo1" class="Foo"/>
<bean id="foo2" class="Bar"/>
并尝试按类型自动装配:
@Autowired private Foo aFoo;
我明白了
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [Foo]
自动装配可以使用类型和 bean 名称来工作,具体取决于您的配置方式。
在本例中,由于有两个类型为
Foo
的 bean,因此可以选择 Foo
实例,因为它与变量 foo
的名称匹配。
如果将
foo
重命名为其他名称会发生什么?
如果有两个相同类型的bean,那么spring会尝试通过您指定的变量名称来解决依赖关系。如果名称与任何 bean 名称不匹配,则会抛出错误。但是,如果它找到与您指定的变量名称匹配的 bean 名称,它将注入该 bean。 因此,在注入依赖项时,spring 会同时考虑类型和名称。
另一个原因是因为 Foo 类没有用 @ConditionalOnMissingBean(Foo.class) 注解。此注释可确保如果上下文中存在另一个 Foo 类型的 bean(即 Bar),则不会创建 Foo 类的实例。