diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java index 1b5682d25d..dfc60e36c4 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -172,6 +172,44 @@ public abstract class BeanFactoryUtils { return result; } + /** + * Get all bean names for the given type, including those defined in ancestor + * factories. Will return unique names in case of overridden bean definitions. + *
Does consider objects created by FactoryBeans if the "allowEagerInit" + * flag is set, which means that FactoryBeans will get initialized. If the + * object created by the FactoryBean doesn't match, the raw FactoryBean itself + * will be matched against the type. If "allowEagerInit" is not set, + * only raw FactoryBeans will be checked (which doesn't require initialization + * of each FactoryBean). + * @param lbf the bean factory + * @param includeNonSingletons whether to include prototype or scoped beans too + * or just singletons (also applies to FactoryBeans) + * @param allowEagerInit whether to initialize lazy-init singletons and + * objects created by FactoryBeans (or by factory methods with a + * "factory-bean" reference) for the type check. Note that FactoryBeans need to be + * eagerly initialized to determine their type: So be aware that passing in "true" + * for this flag will initialize FactoryBeans and "factory-bean" references. + * @param type the type that beans must match (as a {@code ResolvableType}) + * @return the array of matching bean names, or an empty array if none + * @since 5.2 + * @see ListableBeanFactory#getBeanNamesForType(ResolvableType, boolean, boolean) + */ + public static String[] beanNamesForTypeIncludingAncestors( + ListableBeanFactory lbf, ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { + + Assert.notNull(lbf, "ListableBeanFactory must not be null"); + String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit); + if (lbf instanceof HierarchicalBeanFactory) { + HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf; + if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) { + String[] parentResult = beanNamesForTypeIncludingAncestors( + (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit); + result = mergeNamesWithParent(result, parentResult, hbf); + } + } + return result; + } + /** * Get all bean names for the given type, including those defined in ancestor * factories. Will return unique names in case of overridden bean definitions. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java index 0fc8d08686..09f0f5dade 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java @@ -116,6 +116,40 @@ public interface ListableBeanFactory extends BeanFactory { */ String[] getBeanNamesForType(ResolvableType type); + /** + * Return the names of beans matching the given type (including subclasses), + * judging from either bean definitions or the value of {@code getObjectType} + * in the case of FactoryBeans. + *
NOTE: This method introspects top-level beans only. It does not + * check nested beans which might match the specified type as well. + *
Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set, + * which means that FactoryBeans will get initialized. If the object created by the + * FactoryBean doesn't match, the raw FactoryBean itself will be matched against the + * type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked + * (which doesn't require initialization of each FactoryBean). + *
Does not consider any hierarchy this factory may participate in. + * Use BeanFactoryUtils' {@code beanNamesForTypeIncludingAncestors} + * to include beans in ancestor factories too. + *
Note: Does not ignore singleton beans that have been registered + * by other means than bean definitions. + *
Bean names returned by this method should always return bean names in the
+ * order of definition in the backend configuration, as far as possible.
+ * @param type the generically typed class or interface to match
+ * @param includeNonSingletons whether to include prototype or scoped beans too
+ * or just singletons (also applies to FactoryBeans)
+ * @param allowEagerInit whether to initialize lazy-init singletons and
+ * objects created by FactoryBeans (or by factory methods with a
+ * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
+ * eagerly initialized to determine their type: So be aware that passing in "true"
+ * for this flag will initialize FactoryBeans and "factory-bean" references.
+ * @return the names of beans (or objects created by FactoryBeans) matching
+ * the given object type (including subclasses), or an empty array if none
+ * @since 5.2
+ * @see FactoryBean#getObjectType
+ * @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, ResolvableType, boolean, boolean)
+ */
+ String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
+
/**
* Return the names of beans matching the given type (including subclasses),
* judging from either bean definitions or the value of {@code getObjectType}
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 8a6052bc76..c94ae2cfde 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
@@ -463,12 +463,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public String[] getBeanNamesForType(ResolvableType type) {
+ return getBeanNamesForType(type, true, true);
+ }
+
+ @Override
+ public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
Class> resolved = type.resolve();
if (resolved != null && !type.hasGenerics()) {
- return getBeanNamesForType(resolved, true, true);
+ return getBeanNamesForType(resolved, includeNonSingletons, includeNonSingletons);
}
else {
- return doGetBeanNamesForType(type, true, true);
+ return doGetBeanNamesForType(type, includeNonSingletons, includeNonSingletons);
}
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
index 2d894a6c30..ee364317e3 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -329,26 +329,32 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Override
public String[] getBeanNamesForType(@Nullable ResolvableType type) {
- boolean isFactoryType = false;
- if (type != null) {
- Class> resolved = type.resolve();
- if (resolved != null && FactoryBean.class.isAssignableFrom(resolved)) {
- isFactoryType = true;
- }
- }
+ return getBeanNamesForType(type, true, true);
+ }
+
+
+ @Override
+ public String[] getBeanNamesForType(@Nullable ResolvableType type,
+ boolean includeNonSingletons, boolean allowEagerInit) {
+
+ Class> resolved = (type != null ? type.resolve() : null);
+ boolean isFactoryType = resolved != null && FactoryBean.class.isAssignableFrom(resolved);
List