gpt4 book ai didi

java - @Autowired 和 default-autowire 可以共存吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:23:14 27 4
gpt4 key购买 nike

<beans default-autowire="byType />

意味着如果具有所需类型的 bean 不超过 1 个,bean 的所有字段将自动注入(inject)依赖项。

问题是当使用注解时它是如何工作的,它到底能不能工作。

我的测试表明即使我使用

@Resource(name="someConcreteFoo")
private Foo foo;

如果 Foo 有多个实现,上下文会尝试按类型 Autowiring 字段,但会失败.所以,就我所见,default-autowire不与注释混合。我在文档中找不到任何具体内容。

扩展问题 - 当使用 xml-only 时,spring 如何使用默认 Autowiring 。 IE。如果你有 <property> .属性注入(inject)是否覆盖默认值(应该是)。

我可以做更多的测试,但我更喜欢通过一些引用来确认行为。有什么见解吗?

最佳答案

我快速调试了这个问题,我认为这很可能是 spring 中的一个错误。在我看来,问题源于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);
}

我个人认为应用 Autowiring 和 InstantiationAwareBeanPostProcessor 的顺序是错误的,因为 @Resource 注释只会在 postProcessPropertyValues 中应用,所以在 Autowiring 之后(此时 Autowiring 已经失败)。

现在我不知道更改调用顺序是否会产生影响,以便在 Autowiring 之前解决 @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);
}
};
}
};

希望对你有帮助

关于java - @Autowired 和 default-autowire 可以共存吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5145351/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com