diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index e6da6cabaf8..5663a820d91 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -724,19 +724,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac int minNrOfArgs = (mbd.hasConstructorArgumentValues() ? mbd.getConstructorArgumentValues().getArgumentCount() : 0); Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass); - for (Method factoryMethod : candidates) { - if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic && - factoryMethod.getName().equals(mbd.getFactoryMethodName()) && - factoryMethod.getParameterCount() >= minNrOfArgs) { + for (Method candidate : candidates) { + if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate) && + candidate.getParameterCount() >= minNrOfArgs) { // Declared type variables to inspect? - if (factoryMethod.getTypeParameters().length > 0) { + if (candidate.getTypeParameters().length > 0) { try { // Fully resolve parameter names and argument values. - Class[] paramTypes = factoryMethod.getParameterTypes(); + Class[] paramTypes = candidate.getParameterTypes(); String[] paramNames = null; ParameterNameDiscoverer pnd = getParameterNameDiscoverer(); if (pnd != null) { - paramNames = pnd.getParameterNames(factoryMethod); + paramNames = pnd.getParameterNames(candidate); } ConstructorArgumentValues cav = mbd.getConstructorArgumentValues(); Set usedValueHolders = new HashSet<>(paramTypes.length); @@ -753,9 +752,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } Class returnType = AutowireUtils.resolveReturnTypeForFactoryMethod( - factoryMethod, args, getBeanClassLoader()); - uniqueCandidate = (commonType == null && returnType == factoryMethod.getReturnType() ? - factoryMethod : null); + candidate, args, getBeanClassLoader()); + uniqueCandidate = (commonType == null && returnType == candidate.getReturnType() ? + candidate : null); commonType = ClassUtils.determineCommonAncestor(returnType, commonType); if (commonType == null) { // Ambiguous return types found: return null to indicate "not determinable". @@ -769,8 +768,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } else { - uniqueCandidate = (commonType == null ? factoryMethod : null); - commonType = ClassUtils.determineCommonAncestor(factoryMethod.getReturnType(), commonType); + uniqueCandidate = (commonType == null ? candidate : null); + commonType = ClassUtils.determineCommonAncestor(candidate.getReturnType(), commonType); if (commonType == null) { // Ambiguous return types found: return null to indicate "not determinable". return null; @@ -1281,7 +1280,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean - * @param bw BeanWrapper with bean instance + * @param bw the BeanWrapper with bean instance */ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { @@ -1370,7 +1369,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param beanName the name of the bean we're wiring up. * Useful for debugging messages; not used functionally. * @param mbd bean definition to update through autowiring - * @param bw BeanWrapper from which we can obtain information about the bean + * @param bw the BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByName( @@ -1404,7 +1403,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * behavior for bigger applications. * @param beanName the name of the bean to autowire by type * @param mbd the merged bean definition to update through autowiring - * @param bw BeanWrapper from which we can obtain information about the bean + * @param bw the BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByType( diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java index 19f96e8caf0..5aa861ae752 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java @@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Arrays; import java.util.List; +import java.util.Map; import javax.annotation.PostConstruct; import org.junit.Before; @@ -809,6 +810,15 @@ public class ConfigurationClassPostProcessorTests { assertSame(ctx.getBean(TestBean.class), bean.testBeans.get(0)); } + @Test + public void testMapInjectionFromSameConfigurationClass() { + ApplicationContext ctx = new AnnotationConfigApplicationContext(MapInjectionConfiguration.class); + MapInjectionConfiguration bean = ctx.getBean(MapInjectionConfiguration.class); + assertNotNull(bean.testBeans); + assertEquals(1, bean.testBeans.size()); + assertSame(ctx.getBean(Runnable.class), bean.testBeans.get("testBean")); + } + @Test public void testBeanLookupFromSameConfigurationClass() { ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanLookupConfiguration.class); @@ -1566,6 +1576,23 @@ public class ConfigurationClassPostProcessorTests { } } + @Configuration + public static class MapInjectionConfiguration { + + @Autowired + private Map testBeans; + + @Bean + Runnable testBean() { + return () -> {}; + } + + // Unrelated, not to be considered as a factory method + private boolean testBean(boolean param) { + return param; + } + } + @Configuration static abstract class BeanLookupConfiguration {