Spring bean 如何@Autowire
:byName 或 byType?如果不可能,是否使用另一种模式进行第二次试验?
6 回答
如果使用它进行注解,@Autowired
则会注入匹配类型的 bean(如果有多个类型,则会引发异常)。要指定名称,请使用@Qualifier
注释。
按类型弹簧@Autowire
线。对于按名称接线,您也可以使用
@Resource(name = "id")
的默认模式@Autowired
是byType
.
Autowired
变量或 setters 方法上的注释等效于 xml 属性autowire="byType"
XML 属性autowire
默认为no
"no":
The traditional Spring default. No automagical wiring. Bean references
must be defined in the XML file via the <ref/> element (or "ref"
attribute). We recommend this in most cases as it makes documentation
more explicit.
它们是 no、byName、byType、constructor 和 autodetect。默认模式是 no,即在传统的基于 XML 的配置中默认自动装配是关闭的。
使用@Autowired 注解-
1)@Autowired 属性:
在属性上使用@Autowired 时,相当于配置文件中的byType 自动装配。
2) @Autowired 在属性设置器上:
在 setter 上使用 @Autowired 时,也相当于配置文件中的 byType 自动装配。
3) @Autowired 在构造函数上:
在bean的构造函数上使用@Autowired时,也相当于配置文件中的构造函数自动装配。
使用 @Qualifier 解决依赖关系中的冲突
正如我们所了解的,如果我们在 byType 模式下使用自动装配,并且会查找属性类类型的依赖项。如果未找到此类类型,则会引发错误。但是,如果同一类类型有两个或多个 bean 怎么办。
在这种情况下,spring 将无法选择正确的 bean 注入属性,您需要使用限定符来帮助容器。
要使用限定符解析特定的 bean,我们需要使用 @Qualifier 注释和 @Autowired 注释,并在注释参数中传递 bean 名称。
我刚刚查看了 spring-beans-5.2.7.RELEASE.jar 的源代码。它包含类 DefaultListableBeanFactory 和方法
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
正如我们所见,它尝试按类型自动装配。如果没有成功,它会尝试在此行中按名称自动装配
matchesBeanName(candidateName, descriptor.getDependencyName()))