Use bean-creating factory's AutowireCandidateResolver even for dependencies in parent factory
Specifically, if the current factory has Qualifier/ContextAnnotationAutowireCandidateResolver set up, it is important to pass it on to ancestor factories to get consistent qualifier matching results. Issue: SPR-10966
This commit is contained in:
parent
be63c07b2e
commit
eb1b3c5a68
|
|
@ -567,15 +567,33 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the specified bean definition qualifies as an autowire candidate,
|
||||
* to be injected into other beans which declare a dependency of matching type.
|
||||
* @param beanName the name of the bean definition to check
|
||||
* @param descriptor the descriptor of the dependency to resolve
|
||||
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
|
||||
* @return whether the bean should be considered as autowire candidate
|
||||
*/
|
||||
protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
|
||||
if (containsBeanDefinition(beanDefinitionName)) {
|
||||
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor);
|
||||
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver);
|
||||
}
|
||||
else if (containsSingleton(beanName)) {
|
||||
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor);
|
||||
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
|
||||
// No bean definition found in this factory -> delegate to parent.
|
||||
return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
|
||||
}
|
||||
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
|
||||
// No bean definition found in this factory -> delegate to parent.
|
||||
// If no DefaultListableBeanFactory, can't pass the resolver along.
|
||||
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
|
||||
}
|
||||
else {
|
||||
|
|
@ -589,9 +607,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
* @param beanName the name of the bean definition to check
|
||||
* @param mbd the merged bean definition to check
|
||||
* @param descriptor the descriptor of the dependency to resolve
|
||||
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
|
||||
* @return whether the bean should be considered as autowire candidate
|
||||
*/
|
||||
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) {
|
||||
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
|
||||
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
|
||||
|
||||
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
|
||||
resolveBeanClass(mbd, beanDefinitionName);
|
||||
if (mbd.isFactoryMethodUnique) {
|
||||
|
|
@ -603,7 +624,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
|
||||
}
|
||||
}
|
||||
return getAutowireCandidateResolver().isAutowireCandidate(
|
||||
return resolver.isAutowireCandidate(
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,14 +16,12 @@
|
|||
|
||||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
|
|
@ -31,8 +29,13 @@ import org.springframework.beans.factory.FactoryBean;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.util.ClassUtils.*;
|
||||
|
||||
/**
|
||||
|
|
@ -74,6 +77,31 @@ public final class QualifierAnnotationTests {
|
|||
assertEquals("Larry", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQualifiedByParentValue() {
|
||||
StaticApplicationContext parent = new StaticApplicationContext();
|
||||
GenericBeanDefinition parentLarry = new GenericBeanDefinition();
|
||||
parentLarry.setBeanClass(Person.class);
|
||||
parentLarry.getPropertyValues().add("name", "ParentLarry");
|
||||
parentLarry.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "parentLarry"));
|
||||
parent.registerBeanDefinition("someLarry", parentLarry);
|
||||
GenericBeanDefinition otherLarry = new GenericBeanDefinition();
|
||||
otherLarry.setBeanClass(Person.class);
|
||||
otherLarry.getPropertyValues().add("name", "OtherLarry");
|
||||
otherLarry.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "otherLarry"));
|
||||
parent.registerBeanDefinition("someOtherLarry", otherLarry);
|
||||
parent.refresh();
|
||||
|
||||
StaticApplicationContext context = new StaticApplicationContext(parent);
|
||||
BeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
|
||||
reader.loadBeanDefinitions(CONFIG_LOCATION);
|
||||
context.registerSingleton("testBean", QualifiedByParentValueTestBean.class);
|
||||
context.refresh();
|
||||
QualifiedByParentValueTestBean testBean = (QualifiedByParentValueTestBean) context.getBean("testBean");
|
||||
Person person = testBean.getLarry();
|
||||
assertEquals("ParentLarry", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQualifiedByBeanName() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
|
@ -222,6 +250,17 @@ public final class QualifierAnnotationTests {
|
|||
}
|
||||
|
||||
|
||||
private static class QualifiedByParentValueTestBean {
|
||||
|
||||
@Autowired @Qualifier("parentLarry")
|
||||
private Person larry;
|
||||
|
||||
public Person getLarry() {
|
||||
return larry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class QualifiedByBeanNameTestBean {
|
||||
|
||||
@Autowired @Qualifier("larryBean")
|
||||
|
|
|
|||
Loading…
Reference in New Issue