BeanMethodInterceptor forwards user-provided arguments to getBean(name, args)

Issue: SPR-12443
This commit is contained in:
Juergen Hoeller 2014-11-22 16:06:25 +01:00
parent 75c70fac3d
commit 4bd75e4146
3 changed files with 82 additions and 32 deletions

View File

@ -45,6 +45,7 @@ import org.springframework.cglib.transform.ClassEmitterTransformer;
import org.springframework.cglib.transform.TransformingClassGenerator; import org.springframework.cglib.transform.TransformingClassGenerator;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@ -321,7 +322,8 @@ class ConfigurationClassEnhancer {
if (alreadyInCreation) { if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false); beanFactory.setCurrentlyInCreation(beanName, false);
} }
return beanFactory.getBean(beanName); return (!ObjectUtils.isEmpty(beanMethodArgs) ?
beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
} }
finally { finally {
if (alreadyInCreation) { if (alreadyInCreation) {

View File

@ -468,6 +468,12 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Test
public void testPrototypeArgumentsThroughBeanMethodCall() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfig.class);
ctx.getBean(FooFactory.class).createFoo(new BarArgument());
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -925,4 +931,38 @@ public class ConfigurationClassPostProcessorTests {
public static class Z { public static class Z {
} }
@Configuration
static class BeanArgumentConfig {
@Bean
@Scope("prototype")
public DependingFoo foo(final BarArgument bar) {
return new DependingFoo(bar);
}
@Bean
public FooFactory fooFactory() {
return new FooFactory() {
@Override
public DependingFoo createFoo(final BarArgument bar) {
return foo(bar);
}
};
}
}
static class BarArgument {
}
static class DependingFoo {
DependingFoo(BarArgument bar) {
}
}
static abstract class FooFactory {
abstract DependingFoo createFoo(BarArgument bar);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,34 +34,40 @@ import static org.junit.Assert.*;
* @since 3.1 * @since 3.1
*/ */
public class ConfigurationWithFactoryBeanAndParametersTests { public class ConfigurationWithFactoryBeanAndParametersTests {
@Test @Test
public void test() { public void test() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class, Bar.class); ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class, Bar.class);
assertNotNull(ctx.getBean(Bar.class).foo); assertNotNull(ctx.getBean(Bar.class).foo);
} }
}
@Configuration
class Config { @Configuration
static class Config {
@Bean @Bean
public FactoryBean<Foo> fb(@Value("42") String answer) { public FactoryBean<Foo> fb(@Value("42") String answer) {
return new FooFactoryBean(); return new FooFactoryBean();
} }
} }
class Foo {
}
class Bar { static class Foo {
}
static class Bar {
Foo foo; Foo foo;
@Autowired @Autowired
public Bar(Foo foo) { public Bar(Foo foo) {
this.foo = foo; this.foo = foo;
} }
} }
class FooFactoryBean implements FactoryBean<Foo> {
static class FooFactoryBean implements FactoryBean<Foo> {
@Override @Override
public Foo getObject() { public Foo getObject() {
@ -77,4 +83,6 @@ class FooFactoryBean implements FactoryBean<Foo> {
public boolean isSingleton() { public boolean isSingleton() {
return true; return true;
} }
}
} }