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 81b083cadf5..2e9580b6c6f 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-2022 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -40,10 +40,14 @@ import org.springframework.util.StringUtils;
* (which the methods defined on the ListableBeanFactory interface don't,
* in contrast to the methods defined on the BeanFactory interface).
*
+ *
NOTE: It is generally preferable to use {@link ObjectProvider#stream()}
+ * via {@link BeanFactory#getBeanProvider} instead of this utility class.
+ *
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
* @since 04.07.2003
+ * @see BeanFactory#getBeanProvider
*/
public abstract class BeanFactoryUtils {
@@ -309,7 +313,7 @@ public abstract class BeanFactoryUtils {
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean to match
* @return the Map of matching bean instances, or an empty Map if none
* @throws BeansException if a bean could not be created
* @see ListableBeanFactory#getBeansOfType(Class)
@@ -348,7 +352,7 @@ public abstract class BeanFactoryUtils {
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean 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
@@ -396,7 +400,7 @@ public abstract class BeanFactoryUtils {
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean to match
* @return the matching bean instance
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
@@ -426,7 +430,7 @@ public abstract class BeanFactoryUtils {
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean 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
@@ -458,7 +462,7 @@ public abstract class BeanFactoryUtils {
*
This version of {@code beanOfType} automatically includes
* prototypes and FactoryBeans.
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean to match
* @return the matching bean instance
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
@@ -482,7 +486,7 @@ public abstract class BeanFactoryUtils {
* only raw FactoryBeans will be checked (which doesn't require initialization
* of each FactoryBean).
* @param lbf the bean factory
- * @param type type of bean to match
+ * @param type the type of bean 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
@@ -530,7 +534,7 @@ public abstract class BeanFactoryUtils {
/**
* Extract a unique bean for the given type from the given Map of matching beans.
- * @param type type of bean to match
+ * @param type the type of bean to match
* @param matchingBeans all matching beans found
* @return the unique bean instance
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java b/spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java
index a2cdfb4ffa8..2768d066c3b 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java
@@ -56,10 +56,13 @@ import org.springframework.core.OrderComparator;
public interface ObjectProvider extends ObjectFactory, Iterable {
/**
- * A predicate for unfiltered type matches.
+ * A predicate for unfiltered type matches, including non-default candidates
+ * but still excluding non-autowire candidates when used on injection points.
* @since 6.2.3
* @see #stream(Predicate)
* @see #orderedStream(Predicate)
+ * @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
+ * @see org.springframework.beans.factory.support.AbstractBeanDefinition#isDefaultCandidate()
*/
Predicate> UNFILTERED = (clazz -> true);
@@ -209,7 +212,7 @@ public interface ObjectProvider extends ObjectFactory, Iterable {
* without specific ordering guarantees (but typically in registration order).
*
Note: The result may be filtered by default according to qualifiers on the
* injection point versus target beans and the general autowire candidate status
- * of matching beans. For custom filtering against the raw type matches, use
+ * of matching beans. For custom filtering against type-matching candidates, use
* {@link #stream(Predicate)} instead (potentially with {@link #UNFILTERED}).
* @since 5.1
* @see #iterator()
@@ -234,7 +237,7 @@ public interface ObjectProvider extends ObjectFactory, Iterable {
* if necessary.
*
Note: The result may be filtered by default according to qualifiers on the
* injection point versus target beans and the general autowire candidate status
- * of matching beans. For custom filtering against the raw type matches, use
+ * of matching beans. For custom filtering against type-matching candidates, use
* {@link #stream(Predicate)} instead (potentially with {@link #UNFILTERED}).
* @since 5.1
* @see #stream()
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java
index fc038766219..5a9faf928e8 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java
@@ -35,7 +35,9 @@ import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanMetadataElement;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -260,6 +262,24 @@ abstract class AutowireUtils {
return method.getReturnType();
}
+ /**
+ * Check the autowire-candidate status for the specified bean.
+ * @param beanFactory the bean factory
+ * @param beanName the name of the bean to check
+ * @return whether the specified bean qualifies as an autowire candidate
+ * @since 6.2.3
+ * @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
+ */
+ public static boolean isAutowireCandidate(ConfigurableBeanFactory beanFactory, String beanName) {
+ try {
+ return beanFactory.getMergedBeanDefinition(beanName).isAutowireCandidate();
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ // A manually registered singleton instance not backed by a BeanDefinition.
+ return true;
+ }
+ }
+
/**
* Reflective {@link InvocationHandler} for lazy access to the current target object.
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 659b565aa9e..10ac3533fa3 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
@@ -2480,6 +2480,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public Stream