Skip to content

Commit fa0ef2d

Browse files
committed
BeanFactory accepts getBean arguments for non-prototype beans as well
Issue: SPR-12488
1 parent c5c5473 commit fa0ef2d

File tree

4 files changed

+43
-28
lines changed

4 files changed

+43
-28
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ public interface BeanFactory {
170170
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
171171
* overriding the specified default arguments (if any) in the bean definition.
172172
* @param name the name of the bean to retrieve
173-
* @param args arguments to use if creating a prototype using explicit arguments
173+
* @param args arguments to use when creating a bean instance using explicit arguments
174+
* (only applied when creating a new instance as opposed to retrieving an existing one)
174175
* @return an instance of the bean
175176
* @throws NoSuchBeanDefinitionException if there is no such bean definition
176177
* @throws BeanDefinitionStoreException if arguments have been given but
@@ -190,8 +191,8 @@ public interface BeanFactory {
190191
* but may also be translated into a conventional by-name lookup based on the name
191192
* of the given type. For more extensive retrieval operations across sets of beans,
192193
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
193-
* @param args arguments to use if creating a prototype using explicit arguments to a
194-
* static factory method. It is invalid to use a non-null args value in any other case.
194+
* @param args arguments to use when creating a bean instance using explicit arguments
195+
* (only applied when creating a new instance as opposed to retrieving an existing one)
195196
* @return an instance of the bean
196197
* @throws NoSuchBeanDefinitionException if there is no such bean definition
197198
* @throws BeanDefinitionStoreException if arguments have been given but

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,7 @@ protected Object createBean(final String beanName, final RootBeanDefinition mbd,
487487
* factory method, and autowiring a constructor.
488488
* @param beanName the name of the bean
489489
* @param mbd the merged bean definition for the bean
490-
* @param args arguments to use if creating a prototype using explicit arguments to a
491-
* static factory method. This parameter must be {@code null} except in this case.
490+
* @param args explicit arguments to use for constructor or factory method invocation
492491
* @return a new instance of the bean
493492
* @throws BeanCreationException if the bean could not be created
494493
* @see #instantiateBean
@@ -988,8 +987,7 @@ protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass,
988987
* factory method, constructor autowiring, or simple instantiation.
989988
* @param beanName the name of the bean
990989
* @param mbd the bean definition for the bean
991-
* @param args arguments to use if creating a prototype using explicit arguments to a
992-
* static factory method. It is invalid to use a non-null args value in any other case.
990+
* @param args explicit arguments to use for constructor or factory method invocation
993991
* @return BeanWrapper for the new instance
994992
* @see #instantiateUsingFactoryMethod
995993
* @see #autowireConstructor

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ public Object getBean(String name, Object... args) throws BeansException {
207207
* Return an instance, which may be shared or independent, of the specified bean.
208208
* @param name the name of the bean to retrieve
209209
* @param requiredType the required type of the bean to retrieve
210-
* @param args arguments to use if creating a prototype using explicit arguments to a
211-
* static factory method. It is invalid to use a non-null args value in any other case.
210+
* @param args arguments to use when creating a bean instance using explicit arguments
211+
* (only applied when creating a new instance as opposed to retrieving an existing one)
212212
* @return an instance of the bean
213213
* @throws BeansException if the bean could not be created
214214
*/
@@ -220,8 +220,8 @@ public <T> T getBean(String name, Class<T> requiredType, Object... args) throws
220220
* Return an instance, which may be shared or independent, of the specified bean.
221221
* @param name the name of the bean to retrieve
222222
* @param requiredType the required type of the bean to retrieve
223-
* @param args arguments to use if creating a prototype using explicit arguments to a
224-
* static factory method. It is invalid to use a non-null args value in any other case.
223+
* @param args arguments to use when creating a bean instance using explicit arguments
224+
* (only applied when creating a new instance as opposed to retrieving an existing one)
225225
* @param typeCheckOnly whether the instance is obtained for a type check,
226226
* not for actual use
227227
* @return an instance of the bean
@@ -1266,17 +1266,9 @@ protected RootBeanDefinition getMergedBeanDefinition(
12661266
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
12671267
throws BeanDefinitionStoreException {
12681268

1269-
// check if bean definition is not abstract
12701269
if (mbd.isAbstract()) {
12711270
throw new BeanIsAbstractException(beanName);
12721271
}
1273-
1274-
// Check validity of the usage of the args parameter. This can
1275-
// only be used for prototypes constructed via a factory method.
1276-
if (args != null && !mbd.isPrototype()) {
1277-
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
1278-
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
1279-
}
12801272
}
12811273

12821274
/**
@@ -1619,15 +1611,13 @@ protected void registerDisposableBeanIfNecessary(String beanName, Object bean, R
16191611
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
16201612

16211613
/**
1622-
* Create a bean instance for the given bean definition.
1623-
* The bean definition will already have been merged with the parent
1624-
* definition in case of a child definition.
1625-
* <p>All the other methods in this class invoke this method, although
1626-
* beans may be cached after being instantiated by this method. All bean
1627-
* instantiation within this class is performed by this method.
1614+
* Create a bean instance for the given merged bean definition (and arguments).
1615+
* The bean definition will already have been merged with the parent definition
1616+
* in case of a child definition.
1617+
* <p>All bean retrieval methods delegate to this method for actual bean creation.
16281618
* @param beanName the name of the bean
16291619
* @param mbd the merged bean definition for the bean
1630-
* @param args arguments to use if creating a prototype using explicit arguments
1620+
* @param args explicit arguments to use for constructor or factory method invocation
16311621
* @return a new instance of the bean
16321622
* @throws BeanCreationException if the bean could not be created
16331623
*/

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.springframework.beans.factory.support.ChildBeanDefinition;
3939
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
4040
import org.springframework.beans.factory.support.RootBeanDefinition;
41+
import org.springframework.context.ApplicationContext;
4142
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
4243
import org.springframework.core.env.StandardEnvironment;
4344
import org.springframework.core.io.DescriptiveResource;
@@ -470,7 +471,13 @@ public void testCircularDependencyWithApplicationContext() {
470471

471472
@Test
472473
public void testPrototypeArgumentsThroughBeanMethodCall() {
473-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfig.class);
474+
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithPrototype.class);
475+
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
476+
}
477+
478+
@Test
479+
public void testSingletonArgumentsThroughBeanMethodCall() {
480+
ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithSingleton.class);
474481
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
475482
}
476483

@@ -932,7 +939,7 @@ public static class Z {
932939
}
933940

934941
@Configuration
935-
static class BeanArgumentConfig {
942+
static class BeanArgumentConfigWithPrototype {
936943

937944
@Bean
938945
@Scope("prototype")
@@ -951,6 +958,25 @@ public DependingFoo createFoo(final BarArgument bar) {
951958
}
952959
}
953960

961+
@Configuration
962+
static class BeanArgumentConfigWithSingleton {
963+
964+
@Bean @Lazy
965+
public DependingFoo foo(final BarArgument bar) {
966+
return new DependingFoo(bar);
967+
}
968+
969+
@Bean
970+
public FooFactory fooFactory() {
971+
return new FooFactory() {
972+
@Override
973+
public DependingFoo createFoo(final BarArgument bar) {
974+
return foo(bar);
975+
}
976+
};
977+
}
978+
}
979+
954980
static class BarArgument {
955981
}
956982

0 commit comments

Comments
 (0)