Consistent handling of NullBean instances in resolveNamedBean
Closes gh-26271
This commit is contained in:
parent
fbd2ffdd23
commit
00b56c026a
|
|
@ -250,7 +250,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
|
|
||||||
String beanName = transformedBeanName(name);
|
String beanName = transformedBeanName(name);
|
||||||
Object bean;
|
Object beanInstance;
|
||||||
|
|
||||||
// Eagerly check singleton cache for manually registered singletons.
|
// Eagerly check singleton cache for manually registered singletons.
|
||||||
Object sharedInstance = getSingleton(beanName);
|
Object sharedInstance = getSingleton(beanName);
|
||||||
|
|
@ -264,7 +264,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
|
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
|
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
@ -342,7 +342,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
|
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (mbd.isPrototype()) {
|
else if (mbd.isPrototype()) {
|
||||||
|
|
@ -355,7 +355,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
finally {
|
finally {
|
||||||
afterPrototypeCreation(beanName);
|
afterPrototypeCreation(beanName);
|
||||||
}
|
}
|
||||||
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
|
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
@ -377,7 +377,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
afterPrototypeCreation(beanName);
|
afterPrototypeCreation(beanName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
|
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ex) {
|
catch (IllegalStateException ex) {
|
||||||
throw new ScopeNotActiveException(beanName, scopeName, ex);
|
throw new ScopeNotActiveException(beanName, scopeName, ex);
|
||||||
|
|
@ -395,14 +395,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return adaptBeanInstance(name, beanInstance, requiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
|
||||||
// Check if required type matches the type of the actual bean instance.
|
// Check if required type matches the type of the actual bean instance.
|
||||||
if (requiredType != null && !requiredType.isInstance(bean)) {
|
if (requiredType != null && !requiredType.isInstance(bean)) {
|
||||||
try {
|
try {
|
||||||
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
|
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
|
||||||
if (convertedBean == null) {
|
if (convertedBean == null) {
|
||||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||||
}
|
}
|
||||||
return convertedBean;
|
return (T) convertedBean;
|
||||||
}
|
}
|
||||||
catch (TypeMismatchException ex) {
|
catch (TypeMismatchException ex) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
|
|
|
||||||
|
|
@ -1231,8 +1231,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidateNames.length == 1) {
|
if (candidateNames.length == 1) {
|
||||||
String beanName = candidateNames[0];
|
return resolveNamedBean(candidateNames[0], requiredType, args);
|
||||||
return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
|
|
||||||
}
|
}
|
||||||
else if (candidateNames.length > 1) {
|
else if (candidateNames.length > 1) {
|
||||||
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
|
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
|
||||||
|
|
@ -1251,8 +1250,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
if (candidateName != null) {
|
if (candidateName != null) {
|
||||||
Object beanInstance = candidates.get(candidateName);
|
Object beanInstance = candidates.get(candidateName);
|
||||||
if (beanInstance == null || beanInstance instanceof Class) {
|
if (beanInstance == null) {
|
||||||
beanInstance = getBean(candidateName, requiredType.toClass(), args);
|
return null;
|
||||||
|
}
|
||||||
|
if (beanInstance instanceof Class) {
|
||||||
|
return resolveNamedBean(candidateName, requiredType, args);
|
||||||
}
|
}
|
||||||
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
|
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
|
||||||
}
|
}
|
||||||
|
|
@ -1264,6 +1266,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private <T> NamedBeanHolder<T> resolveNamedBean(
|
||||||
|
String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
|
||||||
|
|
||||||
|
Object bean = getBean(beanName, null, args);
|
||||||
|
if (bean instanceof NullBean) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new NamedBeanHolder<T>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
|
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
|
||||||
|
|
|
||||||
|
|
@ -271,9 +271,15 @@ class AnnotationConfigApplicationContextTests {
|
||||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanA.class), "a")).isTrue();
|
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanA.class), "a")).isTrue();
|
||||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanB.class), "b")).isTrue();
|
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanB.class), "b")).isTrue();
|
||||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanC.class), "c")).isTrue();
|
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanC.class), "c")).isTrue();
|
||||||
|
|
||||||
assertThat(context.getBeansOfType(BeanA.class)).isEmpty();
|
assertThat(context.getBeansOfType(BeanA.class)).isEmpty();
|
||||||
assertThat(context.getBeansOfType(BeanB.class).values().iterator().next()).isSameAs(context.getBean(BeanB.class));
|
assertThat(context.getBeansOfType(BeanB.class).values().iterator().next()).isSameAs(context.getBean(BeanB.class));
|
||||||
assertThat(context.getBeansOfType(BeanC.class).values().iterator().next()).isSameAs(context.getBean(BeanC.class));
|
assertThat(context.getBeansOfType(BeanC.class).values().iterator().next()).isSameAs(context.getBean(BeanC.class));
|
||||||
|
|
||||||
|
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
|
||||||
|
context.getBeanFactory().resolveNamedBean(BeanA.class));
|
||||||
|
assertThat(context.getBeanFactory().resolveNamedBean(BeanB.class).getBeanInstance()).isSameAs(context.getBean(BeanB.class));
|
||||||
|
assertThat(context.getBeanFactory().resolveNamedBean(BeanC.class).getBeanInstance()).isSameAs(context.getBean(BeanC.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue