@Bean method metadata is always being picked from the most concrete subclass
As a side effect, @Bean overrides and overloads work with 'allowBeanDefinitionOverriding'=false as well now. Issue: SPR-10992
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
@@ -24,8 +23,6 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -34,25 +31,33 @@ import static org.junit.Assert.*;
|
||||
* Tests regarding overloading and overriding of bean methods.
|
||||
* Related to SPR-6618.
|
||||
*
|
||||
* Bean-annotated methods should be able to be overridden, just as any regular
|
||||
* method. This is straightforward.
|
||||
*
|
||||
* Bean-annotated methods should be able to be overloaded, though supporting this
|
||||
* is more subtle. Essentially, it must be unambiguous to the container which bean
|
||||
* method to call. A simple way to think about this is that no one Configuration
|
||||
* class may declare two bean methods with the same name. In the case of inheritance,
|
||||
* the most specific subclass bean method will always be the one that is invoked.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public class BeanMethodPolymorphismTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
|
||||
@Test
|
||||
public void beanMethodDetectedOnSuperClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
|
||||
ctx.getBean("testBean", TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanMethodOverriding() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(OverridingConfig.class);
|
||||
ctx.setAllowBeanDefinitionOverriding(false);
|
||||
ctx.refresh();
|
||||
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
|
||||
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
|
||||
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanMethodOverloadingWithoutInheritance() {
|
||||
|
||||
@@ -69,15 +74,25 @@ public class BeanMethodPolymorphismTests {
|
||||
|
||||
@Test
|
||||
public void beanMethodOverloadingWithInheritance() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SubConfig.class);
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(SubConfig.class);
|
||||
ctx.setAllowBeanDefinitionOverriding(false);
|
||||
ctx.refresh();
|
||||
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("aString"));
|
||||
assertThat(ctx.getBean(String.class), equalTo("overloaded5"));
|
||||
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("aString"));
|
||||
}
|
||||
|
||||
// SPR-11025
|
||||
@Test
|
||||
public void beanMethodOverloadingWithInheritanceAndList() {
|
||||
// SPR-11025
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SubConfigWithList.class);
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(SubConfigWithList.class);
|
||||
ctx.setAllowBeanDefinitionOverriding(false);
|
||||
ctx.refresh();
|
||||
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("aString"));
|
||||
assertThat(ctx.getBean(String.class), equalTo("overloaded5"));
|
||||
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("aString"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,20 +106,6 @@ public class BeanMethodPolymorphismTests {
|
||||
assertThat(ctx.getBean(String.class), equalTo("shadow"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that polymorphic Configuration classes need not explicitly redeclare the
|
||||
* {@link Configuration} annotation. This respects the {@link Inherited} nature
|
||||
* of the Configuration annotation, even though it's being detected via ASM.
|
||||
*/
|
||||
@Test
|
||||
public void beanMethodsDetectedOnSuperClass() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(Config.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
beanFactory.getBean("testBean", TestBean.class);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class BaseConfig {
|
||||
@@ -113,7 +114,6 @@ public class BeanMethodPolymorphismTests {
|
||||
public TestBean testBean() {
|
||||
return new TestBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,22 @@ public class BeanMethodPolymorphismTests {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class OverridingConfig extends BaseConfig {
|
||||
|
||||
@Bean @Lazy
|
||||
@Override
|
||||
public TestBean testBean() {
|
||||
return new TestBean() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "overridden";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class SuperConfig {
|
||||
|
||||
@@ -140,7 +156,7 @@ public class BeanMethodPolymorphismTests {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Bean @Lazy
|
||||
String aString(Integer dependency) {
|
||||
return "overloaded" + dependency;
|
||||
}
|
||||
@@ -155,7 +171,7 @@ public class BeanMethodPolymorphismTests {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Bean @Lazy
|
||||
String aString(List<Integer> dependency) {
|
||||
return "overloaded" + dependency.get(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user