diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index cbe60f9a525..b8ee9acb4b1 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -58,6 +58,7 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanNotOfRequiredTypeException; import org.springframework.beans.factory.CannotLoadBeanClassException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InjectionPoint; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException; @@ -196,8 +197,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto /** Map from bean name to merged BeanDefinitionHolder. */ private final Map mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256); - /** Set of bean definition names with a primary marker. */ - private final Set primaryBeanNames = ConcurrentHashMap.newKeySet(16); + /** Map of bean definition names with a primary marker plus corresponding type. */ + private final Map> primaryBeanNamesWithType = new ConcurrentHashMap<>(16); /** Map of singleton and non-singleton bean names, keyed by dependency type. */ private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64); @@ -1037,7 +1038,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto protected void cacheMergedBeanDefinition(RootBeanDefinition mbd, String beanName) { super.cacheMergedBeanDefinition(mbd, beanName); if (mbd.isPrimary()) { - this.primaryBeanNames.add(beanName); + this.primaryBeanNamesWithType.put(beanName, Void.class); } } @@ -1313,7 +1314,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto // Cache a primary marker for the given bean. if (beanDefinition.isPrimary()) { - this.primaryBeanNames.add(beanName); + this.primaryBeanNamesWithType.put(beanName, Void.class); } } @@ -1405,7 +1406,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto destroySingleton(beanName); // Remove a cached primary marker for the given bean. - this.primaryBeanNames.remove(beanName); + this.primaryBeanNamesWithType.remove(beanName); // Notify all post-processors that the specified bean definition has been reset. for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) { @@ -1458,9 +1459,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @Override protected void addSingleton(String beanName, Object singletonObject) { super.addSingleton(beanName, singletonObject); + Predicate> filter = (beanType -> beanType != Object.class && beanType.isInstance(singletonObject)); this.allBeanNamesByType.keySet().removeIf(filter); this.singletonBeanNamesByType.keySet().removeIf(filter); + + if (this.primaryBeanNamesWithType.containsKey(beanName) && singletonObject.getClass() != NullBean.class) { + Class beanType = (singletonObject instanceof FactoryBean fb ? + getTypeForFactoryBean(fb) : singletonObject.getClass()); + if (beanType != null) { + this.primaryBeanNamesWithType.put(beanName, beanType); + } + } } @Override @@ -2268,8 +2278,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto * not matching the given bean name. */ private boolean hasPrimaryConflict(String beanName, Class dependencyType) { - for (String candidate : this.primaryBeanNames) { - if (isTypeMatch(candidate, dependencyType) && !candidate.equals(beanName)) { + for (Map.Entry> candidate : this.primaryBeanNamesWithType.entrySet()) { + String candidateName = candidate.getKey(); + Class candidateType = candidate.getValue(); + if (!candidateName.equals(beanName) && (candidateType != Void.class ? + dependencyType.isAssignableFrom(candidateType) : // cached singleton class for primary bean + isTypeMatch(candidateName, dependencyType))) { // not instantiated yet or not a singleton return true; } }