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#resolveNamedBeanwill return suchNullBeanfor the type it has been defined againstorg.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.