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 de743f4d32f..cc583440419 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 @@ -695,19 +695,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac Method uniqueCandidate = null; int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount(); Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass); - for (Method factoryMethod : candidates) { - if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic && - factoryMethod.getName().equals(mbd.getFactoryMethodName()) && - factoryMethod.getParameterTypes().length >= minNrOfArgs) { + for (Method candidate : candidates) { + if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate) && + candidate.getParameterTypes().length >= 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 = @@ -725,10 +724,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } Class returnType = AutowireUtils.resolveReturnTypeForFactoryMethod( - factoryMethod, args, getBeanClassLoader()); + candidate, args, getBeanClassLoader()); if (returnType != null) { - uniqueCandidate = (commonType == null && returnType == factoryMethod.getReturnType() ? - factoryMethod : null); + 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". @@ -743,8 +742,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; @@ -1057,7 +1056,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation - * @return BeanWrapper for the new instance + * @return a BeanWrapper for the new instance * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean @@ -1137,7 +1136,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean - * @return BeanWrapper for the new instance + * @return a BeanWrapper for the new instance */ protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { @@ -1172,7 +1171,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param mbd the bean definition for the bean * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) - * @return BeanWrapper for the new instance + * @return a BeanWrapper for the new instance * @see #getBean(String, Object[]) */ protected BeanWrapper instantiateUsingFactoryMethod( @@ -1193,7 +1192,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @param ctors the chosen candidate constructors * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) - * @return BeanWrapper for the new instance + * @return a BeanWrapper for the new instance */ protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor[] ctors, Object[] explicitArgs) { @@ -1206,7 +1205,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, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); @@ -1290,7 +1289,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( @@ -1324,7 +1323,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 3d6f8c8e956..dcf2f373d51 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -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; @@ -783,6 +784,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); @@ -1468,6 +1478,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 {