<beans default-autowire="byType />
表示如果不超过1个具有所需类型的bean,则bean的所有字段将自动注入依赖项。
问题是当使用注释时这是如何工作的,并且根本不起作用。
我的测试显示,即使我使用
@Resource(name="someConcreteFoo")
private Foo foo;
上下文尝试按类型自动装配字段,如果有Foo
的多个实现,则会失败。因此,对于我所看到的,default-autowire
不会与注释混在一起。我在文档中找不到任何具体内容。
扩展问题 - 当使用xml-only时,spring如何使用default-autowiring进行操作。即如果你有<property>
。属性注入是否覆盖默认值(应该是)。
我可以做更多测试,但我更喜欢某些引文确认的行为。任何见解?
答案 0 :(得分:3)
我快速尝试调试此问题,我认为这可能是春天的错误。在我看来,问题源于AbstractAutowireCapableBeanFactory
中的以下代码/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
applyPropertyValues(beanName, mbd, bw, pvs);
}
我个人认为应用自动装配和InstantiationAwareBeanPostProcessor的顺序是错误的,因为@Resource注释只会应用在postProcessPropertyValues中,因此在自动装配之后(此时自动装配已经失败)。
现在我不知道是否会对更改调用顺序产生影响,因此@Resource注释会在自动装配之前得到解决,但这可能会引发错误/修复(我使用了以下加载我的测试应用程序上下文来解决此问题的方法):
ApplicationContext ctx = new ClassPathXmlApplicationContext("test/appctx.xml") {
protected org.springframework.beans.factory.support.DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory()) {
protected void populateBean(String beanName, org.springframework.beans.factory.support.AbstractBeanDefinition mbd, org.springframework.beans.BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
applyPropertyValues(beanName, mbd, bw, pvs);
}
};
}
};
希望有所帮助
答案 1 :(得分:1)
编辑:
属性注入是否覆盖默认值(应该是)。
你是对的。如果您不希望Spring将依赖项注入bean的某个字段,则可以使用@Qualifier
注释来注入所需的依赖项。我仍然试图找到可以确认它的文档 - 我能找到的最接近的帖子是春季论坛override default-autowire setting with an annotation?
编辑:这是另一篇帖子@Resource considered only after default-autowire="byName",它描述了使用新的InstantiationAwareBeanPostProcessor
来更改布线顺序,以使setter上的@Resource优先于默认自动装置。
答案 2 :(得分:0)
据我所知,default-autowire属性为仅在XML配置中连接的bean定义了默认的“autowire mode”!然后基于注释的自动装配与此无关。 @Autowired
按类型始终,@Resource
按名称始终!
请参阅Spring的参考文档3.9.3中的提示:
“如果您打算按名称表达注释驱动的注入,请不要主要使用@Autowired,即使技术上能够通过@Qualifier值引用bean名称。而是使用JSR-250 @Resource注释,语义定义为通过其唯一名称标识特定目标组件,声明的类型与匹配过程无关。“