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 9803e6b1eb72..82315acbf07e 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 @@ -614,93 +614,117 @@ public String[] getBeanNamesForType(@Nullable Class type, boolean includeNonS private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { List result = new ArrayList<>(); - // Check all bean definitions. + processBeanDefinitions(result, type, includeNonSingletons, allowEagerInit); + processManualSingletons(result, type, includeNonSingletons); + + return StringUtils.toStringArray(result); + } + + private void processBeanDefinitions(List result, ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { for (String beanName : this.beanDefinitionNames) { - // Only consider bean as eligible if the bean name is not defined as alias for some other bean. - if (!isAlias(beanName)) { - try { - RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); - // Only check bean definition if it is complete. - if (!mbd.isAbstract() && (allowEagerInit || - (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) && - !requiresEagerInitForType(mbd.getFactoryBeanName()))) { - boolean isFactoryBean = isFactoryBean(beanName, mbd); - BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); - boolean matchFound = false; - boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName)); - boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit()); - if (!isFactoryBean) { - if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) { - matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); - } - } - else { - if (includeNonSingletons || isNonLazyDecorated) { - matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); - } - else if (allowFactoryBeanInit) { - // Type check before singleton check, avoiding FactoryBean instantiation - // for early FactoryBean.isSingleton() calls on non-matching beans. - matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit) && - isSingleton(beanName, mbd, dbd); - } - if (!matchFound) { - // In case of FactoryBean, try to match FactoryBean instance itself next. - beanName = FACTORY_BEAN_PREFIX + beanName; - if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) { - matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); - } - } + if (isAlias(beanName)) { + continue; + } + + try { + RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); + + // cache merged bean definition + boolean isAbstract = mbd.isAbstract(); + boolean hasBeanClass = mbd.hasBeanClass(); + boolean isLazyInit = mbd.isLazyInit(); + String factoryBeanName = mbd.getFactoryBeanName(); + BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); + + if (shouldSkipBeanDefinition(isAbstract, allowEagerInit, hasBeanClass, isLazyInit, factoryBeanName)) { + continue; + } + + boolean isFactoryBean = isFactoryBean(beanName, mbd); + boolean matchFound = false; + boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName)); + boolean isNonLazyDecorated = (dbd != null && !isLazyInit); + + if (!isFactoryBean && (includeNonSingletons || isSingleton(beanName, mbd, dbd))) { + matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); + } + else { + if (includeNonSingletons || isNonLazyDecorated) { + matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); + } + else if (allowFactoryBeanInit) { + matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit) && + isSingleton(beanName, mbd, dbd); + } + + if (!matchFound) { + String factoryBeanFullName = FACTORY_BEAN_PREFIX + beanName; + if (includeNonSingletons || isSingleton(factoryBeanFullName, mbd, dbd)) { + matchFound = isTypeMatch(factoryBeanFullName, type, allowFactoryBeanInit); } if (matchFound) { - result.add(beanName); + result.add(factoryBeanFullName); + continue; } } } - catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) { - if (allowEagerInit) { - throw ex; - } - // Probably a placeholder: let's ignore it for type matching purposes. - LogMessage message = (ex instanceof CannotLoadBeanClassException ? - LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) : - LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName)); - logger.trace(message, ex); - // Register exception, in case the bean was accidentally unresolvable. - onSuppressedException(ex); + + if (matchFound) { + result.add(beanName); } - catch (NoSuchBeanDefinitionException ex) { - // Bean definition got removed while we were iterating -> ignore. + } + catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) { + if (allowEagerInit) { + throw ex; } + LogMessage message = (ex instanceof CannotLoadBeanClassException ? + LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) : + LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName)); + logger.trace(message, ex); + onSuppressedException(ex); + } + catch (NoSuchBeanDefinitionException ex) { + // Bean definition got removed while we were iterating -> ignore } } + } - // Check manually registered singletons too. + private void processManualSingletons(List result, ResolvableType type, boolean includeNonSingletons) { for (String beanName : this.manualSingletonNames) { try { - // In case of FactoryBean, match object created by FactoryBean. if (isFactoryBean(beanName)) { if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { result.add(beanName); - // Match found for this bean: do not match FactoryBean itself anymore. continue; } - // In case of FactoryBean, try to match FactoryBean itself next. beanName = FACTORY_BEAN_PREFIX + beanName; } - // Match raw bean instance (might be raw FactoryBean). + if (isTypeMatch(beanName, type)) { result.add(beanName); } } catch (NoSuchBeanDefinitionException ex) { - // Shouldn't happen - probably a result of circular reference resolution... logger.trace(LogMessage.format( "Failed to check manually registered singleton with name '%s'", beanName), ex); } } + } - return StringUtils.toStringArray(result); + private boolean shouldSkipBeanDefinition(boolean isAbstract, boolean allowEagerInit, + boolean hasBeanClass, boolean isLazyInit, @Nullable String factoryBeanName) { + + if (isAbstract) { + return true; + } + if (!allowEagerInit) { + boolean needsEagerInit = (!hasBeanClass && isLazyInit && !isAllowEagerClassLoading()) || + requiresEagerInitForType(factoryBeanName); + if (needsEagerInit) { + return true; + } + } + return false; } private boolean isSingleton(String beanName, RootBeanDefinition mbd, @Nullable BeanDefinitionHolder dbd) {