When a @Bean factory returns null, a NullBean is registered in the context that's not meant to be considered when looking for a candidate by type (only a lookup by name would return it).

Unfortunately, that does not work in at least two cases:

  • org.springframework.beans.factory.config.AutowireCapableBeanFactory#resolveNamedBean will return such NullBean for the type it has been defined against
  • org.springframework.beans.factory.ListableBeanFactory#getBeanNamesForType(org.springframework.core.ResolvableType, boolean, boolean) will do that (used by Spring Boot's @ConditionalOnMissingBean.

This was original raised in https://github.com/spring-projects/spring-boot/issues/24448 that contains a sample project.

Comment From: jhoeller

I have revised resolveNamedBean to consistently treat NullBean as not existing, to be committed soon.

However, getBeanNamesForType cannot really handle null return values since we cannot assume that the factory methods have been called at that point. For consistent behavior, we have to include NullBean definitions even when resolved already. As a caller, you'd have to explicitly call getBean for each such candidate and do .equals(null) to find out whether it's a null stub.

Comment From: jhoeller

I wonder whether this resolveNamedBean revision would be needed in 5.2.x as well? It's a high-risk area for subtle regressions, so I'd only do it if Boot 2.3.x actually runs into such scenarios as well.

Comment From: snicoll

The related link is a long standing issue and I am surprised this wasn't raised before, actually. Let me see if there is a workaround first. If there is one we'll document. That sounds a better option than backporting to me.

Comment From: jhoeller

Actually, backporting to 5.2.13 with a release target in February, with the change getting road-tested in the 5.3.3 release in January first, feels ok to me. Backporting is a worthwhile option if this is a common enough problem.