|
58 | 58 | import org.springframework.beans.factory.BeanFactoryUtils;
|
59 | 59 | import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
60 | 60 | import org.springframework.beans.factory.CannotLoadBeanClassException;
|
| 61 | +import org.springframework.beans.factory.FactoryBean; |
61 | 62 | import org.springframework.beans.factory.InjectionPoint;
|
62 | 63 | import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
63 | 64 | import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
@@ -196,8 +197,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
196 | 197 | /** Map from bean name to merged BeanDefinitionHolder. */
|
197 | 198 | private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);
|
198 | 199 |
|
199 |
| - /** Set of bean definition names with a primary marker. */ |
200 |
| - private final Set<String> primaryBeanNames = ConcurrentHashMap.newKeySet(16); |
| 200 | + /** Map of bean definition names with a primary marker plus corresponding type. */ |
| 201 | + private final Map<String, Class<?>> primaryBeanNamesWithType = new ConcurrentHashMap<>(16); |
201 | 202 |
|
202 | 203 | /** Map of singleton and non-singleton bean names, keyed by dependency type. */
|
203 | 204 | private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
|
@@ -1037,7 +1038,7 @@ protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanNam
|
1037 | 1038 | protected void cacheMergedBeanDefinition(RootBeanDefinition mbd, String beanName) {
|
1038 | 1039 | super.cacheMergedBeanDefinition(mbd, beanName);
|
1039 | 1040 | if (mbd.isPrimary()) {
|
1040 |
| - this.primaryBeanNames.add(beanName); |
| 1041 | + this.primaryBeanNamesWithType.put(beanName, Void.class); |
1041 | 1042 | }
|
1042 | 1043 | }
|
1043 | 1044 |
|
@@ -1313,7 +1314,7 @@ else if (isConfigurationFrozen()) {
|
1313 | 1314 |
|
1314 | 1315 | // Cache a primary marker for the given bean.
|
1315 | 1316 | if (beanDefinition.isPrimary()) {
|
1316 |
| - this.primaryBeanNames.add(beanName); |
| 1317 | + this.primaryBeanNamesWithType.put(beanName, Void.class); |
1317 | 1318 | }
|
1318 | 1319 | }
|
1319 | 1320 |
|
@@ -1405,7 +1406,7 @@ protected void resetBeanDefinition(String beanName) {
|
1405 | 1406 | destroySingleton(beanName);
|
1406 | 1407 |
|
1407 | 1408 | // Remove a cached primary marker for the given bean.
|
1408 |
| - this.primaryBeanNames.remove(beanName); |
| 1409 | + this.primaryBeanNamesWithType.remove(beanName); |
1409 | 1410 |
|
1410 | 1411 | // Notify all post-processors that the specified bean definition has been reset.
|
1411 | 1412 | for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
|
@@ -1458,9 +1459,18 @@ protected void checkForAliasCircle(String name, String alias) {
|
1458 | 1459 | @Override
|
1459 | 1460 | protected void addSingleton(String beanName, Object singletonObject) {
|
1460 | 1461 | super.addSingleton(beanName, singletonObject);
|
| 1462 | + |
1461 | 1463 | Predicate<Class<?>> filter = (beanType -> beanType != Object.class && beanType.isInstance(singletonObject));
|
1462 | 1464 | this.allBeanNamesByType.keySet().removeIf(filter);
|
1463 | 1465 | this.singletonBeanNamesByType.keySet().removeIf(filter);
|
| 1466 | + |
| 1467 | + if (this.primaryBeanNamesWithType.containsKey(beanName) && singletonObject.getClass() != NullBean.class) { |
| 1468 | + Class<?> beanType = (singletonObject instanceof FactoryBean<?> fb ? |
| 1469 | + getTypeForFactoryBean(fb) : singletonObject.getClass()); |
| 1470 | + if (beanType != null) { |
| 1471 | + this.primaryBeanNamesWithType.put(beanName, beanType); |
| 1472 | + } |
| 1473 | + } |
1464 | 1474 | }
|
1465 | 1475 |
|
1466 | 1476 | @Override
|
@@ -2268,8 +2278,12 @@ private boolean isSelfReference(@Nullable String beanName, @Nullable String cand
|
2268 | 2278 | * not matching the given bean name.
|
2269 | 2279 | */
|
2270 | 2280 | private boolean hasPrimaryConflict(String beanName, Class<?> dependencyType) {
|
2271 |
| - for (String candidate : this.primaryBeanNames) { |
2272 |
| - if (isTypeMatch(candidate, dependencyType) && !candidate.equals(beanName)) { |
| 2281 | + for (Map.Entry<String, Class<?>> candidate : this.primaryBeanNamesWithType.entrySet()) { |
| 2282 | + String candidateName = candidate.getKey(); |
| 2283 | + Class<?> candidateType = candidate.getValue(); |
| 2284 | + if (!candidateName.equals(beanName) && (candidateType != Void.class ? |
| 2285 | + dependencyType.isAssignableFrom(candidateType) : // cached singleton class for primary bean |
| 2286 | + isTypeMatch(candidateName, dependencyType))) { // not instantiated yet or not a singleton |
2273 | 2287 | return true;
|
2274 | 2288 | }
|
2275 | 2289 | }
|
|
0 commit comments