Resolved SPR-6618. Restrictions were too tight on overloaded bean methods and were preventing it altogether. Overloading is now allowed, as long as there is no ambiguity at runtime which bean method should be invoked.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public class BeanMethodPolymorphismTests {
|
||||
|
||||
@Test
|
||||
public void beanMethodOverloadingWithoutInheritance() {
|
||||
@SuppressWarnings("unused")
|
||||
@Configuration class Config {
|
||||
@Bean String aString() { return "na"; }
|
||||
@Bean String aString(Integer dependency) { return "na"; }
|
||||
}
|
||||
try {
|
||||
new AnnotationConfigApplicationContext(Config.class);
|
||||
fail("expected bean method overloading exception");
|
||||
} catch (BeanDefinitionParsingException ex) {
|
||||
assertTrue(ex.getMessage(), ex.getMessage().contains("2 overloaded @Bean methods named 'aString'"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanMethodOverloadingWithInheritance() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SubConfig.class);
|
||||
assertThat(ctx.getBean(String.class), equalTo("overloaded5"));
|
||||
}
|
||||
static @Configuration class SuperConfig {
|
||||
@Bean String aString() { return "super"; }
|
||||
}
|
||||
static @Configuration class SubConfig {
|
||||
@Bean Integer anInt() { return 5; }
|
||||
@Bean String aString(Integer dependency) { return "overloaded"+dependency; }
|
||||
}
|
||||
|
||||
/**
|
||||
* When inheritance is not involved, it is still possible to override a bean method from
|
||||
* the container's point of view. This is not strictly 'overloading' of a method per se,
|
||||
* so it's referred to here as 'shadowing' to distinguish the difference.
|
||||
*/
|
||||
@Test
|
||||
public void beanMethodShadowing() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ShadowConfig.class);
|
||||
assertThat(ctx.getBean(String.class), equalTo("shadow"));
|
||||
}
|
||||
@Import(SubConfig.class)
|
||||
static @Configuration class ShadowConfig {
|
||||
@Bean String aString() { return "shadow"; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user