Skip to content

Commit

Permalink
Consistent handling of NullBean instances in resolveNamedBean
Browse files Browse the repository at this point in the history
Closes gh-26271
  • Loading branch information
jhoeller committed Dec 16, 2020
1 parent fbd2ffd commit 00b56c0
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ protected <T> T doGetBean(
throws BeansException {

String beanName = transformedBeanName(name);
Object bean;
Object beanInstance;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
Expand All @@ -264,7 +264,7 @@ protected <T> T doGetBean(
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
Expand Down Expand Up @@ -342,7 +342,7 @@ else if (requiredType != null) {
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
Expand All @@ -355,7 +355,7 @@ else if (mbd.isPrototype()) {
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
Expand All @@ -377,7 +377,7 @@ else if (mbd.isPrototype()) {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
Expand All @@ -395,14 +395,19 @@ else if (mbd.isPrototype()) {
}
}

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.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
return (T) convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1231,8 +1231,7 @@ private <T> NamedBeanHolder<T> resolveNamedBean(
}

if (candidateNames.length == 1) {
String beanName = candidateNames[0];
return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
return resolveNamedBean(candidateNames[0], requiredType, args);
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
Expand All @@ -1251,8 +1250,11 @@ else if (candidateNames.length > 1) {
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null || beanInstance instanceof Class) {
beanInstance = getBean(candidateName, requiredType.toClass(), args);
if (beanInstance == null) {
return null;
}
if (beanInstance instanceof Class) {
return resolveNamedBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
}
Expand All @@ -1264,6 +1266,17 @@ else if (candidateNames.length > 1) {
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
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,15 @@ void individualBeanWithNullReturningSupplier() {
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanA.class), "a")).isTrue();
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanB.class), "b")).isTrue();
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanC.class), "c")).isTrue();

assertThat(context.getBeansOfType(BeanA.class)).isEmpty();
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));

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
Expand Down

0 comments on commit 00b56c0

Please sign in to comment.