1616
1717package org .springframework .context .annotation ;
1818
19- import java .lang .annotation .Inherited ;
2019import java .util .List ;
2120
22- import org .junit .Rule ;
2321import org .junit .Test ;
24- import org .junit .rules .ExpectedException ;
2522
26- import org .springframework .beans .factory .parsing .BeanDefinitionParsingException ;
2723import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
2824import org .springframework .beans .factory .support .RootBeanDefinition ;
2925
3430 * Tests regarding overloading and overriding of bean methods.
3531 * Related to SPR-6618.
3632 *
37- * Bean-annotated methods should be able to be overridden, just as any regular
38- * method. This is straightforward.
39- *
40- * Bean-annotated methods should be able to be overloaded, though supporting this
41- * is more subtle. Essentially, it must be unambiguous to the container which bean
42- * method to call. A simple way to think about this is that no one Configuration
43- * class may declare two bean methods with the same name. In the case of inheritance,
44- * the most specific subclass bean method will always be the one that is invoked.
45- *
4633 * @author Chris Beams
4734 * @author Phillip Webb
35+ * @author Juergen Hoeller
4836 */
49- @ SuppressWarnings ("resource" )
5037public class BeanMethodPolymorphismTests {
5138
52- @ Rule
53- public ExpectedException thrown = ExpectedException .none ();
54-
55-
5639 @ Test
5740 public void beanMethodOverloadingWithoutInheritance () {
41+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
42+ ctx .register (ConfigWithOverloading .class );
43+ ctx .setAllowBeanDefinitionOverriding (false );
44+ ctx .refresh ();
45+ assertThat (ctx .getBean (String .class ), equalTo ("regular" ));
46+ }
5847
59- @ SuppressWarnings ({ "hiding" })
60- @ Configuration class Config {
61- @ Bean String aString () { return "na" ; }
62- @ Bean String aString (Integer dependency ) { return "na" ; }
63- }
48+ @ Test
49+ public void beanMethodOverloadingWithoutInheritanceAndExtraDependency () {
50+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
51+ ctx .register (ConfigWithOverloading .class );
52+ ctx .getDefaultListableBeanFactory ().registerSingleton ("anInt" , 5 );
53+ ctx .setAllowBeanDefinitionOverriding (false );
54+ ctx .refresh ();
55+ assertThat (ctx .getBean (String .class ), equalTo ("overloaded5" ));
56+ }
57+
58+ @ Test
59+ public void beanMethodOverloadingWithAdditionalMetadata () {
60+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
61+ ctx .register (ConfigWithOverloadingAndAdditionalMetadata .class );
62+ ctx .setAllowBeanDefinitionOverriding (false );
63+ ctx .refresh ();
64+ assertFalse (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
65+ assertThat (ctx .getBean (String .class ), equalTo ("regular" ));
66+ assertTrue (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
67+ }
6468
65- this .thrown .expect (BeanDefinitionParsingException .class );
66- this .thrown .expectMessage ("overloaded @Bean methods named 'aString'" );
67- new AnnotationConfigApplicationContext (Config .class );
69+ @ Test
70+ public void beanMethodOverloadingWithAdditionalMetadataButOtherMethodExecuted () {
71+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
72+ ctx .register (ConfigWithOverloadingAndAdditionalMetadata .class );
73+ ctx .getDefaultListableBeanFactory ().registerSingleton ("anInt" , 5 );
74+ ctx .setAllowBeanDefinitionOverriding (false );
75+ ctx .refresh ();
76+ assertFalse (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
77+ assertThat (ctx .getBean (String .class ), equalTo ("overloaded5" ));
78+ assertTrue (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
6879 }
6980
7081 @ Test
7182 public void beanMethodOverloadingWithInheritance () {
72- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext (SubConfig .class );
83+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
84+ ctx .register (SubConfig .class );
85+ ctx .setAllowBeanDefinitionOverriding (false );
86+ ctx .refresh ();
87+ assertFalse (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
7388 assertThat (ctx .getBean (String .class ), equalTo ("overloaded5" ));
89+ assertTrue (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
7490 }
7591
92+ // SPR-11025
7693 @ Test
7794 public void beanMethodOverloadingWithInheritanceAndList () {
78- // SPR-11025
79- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext (SubConfigWithList .class );
95+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
96+ ctx .register (SubConfigWithList .class );
97+ ctx .setAllowBeanDefinitionOverriding (false );
98+ ctx .refresh ();
99+ assertFalse (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
80100 assertThat (ctx .getBean (String .class ), equalTo ("overloaded5" ));
101+ assertTrue (ctx .getDefaultListableBeanFactory ().containsSingleton ("aString" ));
81102 }
82103
83104 /**
@@ -91,11 +112,6 @@ public void beanMethodShadowing() {
91112 assertThat (ctx .getBean (String .class ), equalTo ("shadow" ));
92113 }
93114
94- /**
95- * Tests that polymorphic Configuration classes need not explicitly redeclare the
96- * {@link Configuration} annotation. This respects the {@link Inherited} nature
97- * of the Configuration annotation, even though it's being detected via ASM.
98- */
99115 @ Test
100116 public void beanMethodsDetectedOnSuperClass () {
101117 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory ();
@@ -122,6 +138,36 @@ static class Config extends BaseConfig {
122138 }
123139
124140
141+ @ Configuration
142+ static class ConfigWithOverloading {
143+
144+ @ Bean
145+ String aString () {
146+ return "regular" ;
147+ }
148+
149+ @ Bean
150+ String aString (Integer dependency ) {
151+ return "overloaded" + dependency ;
152+ }
153+ }
154+
155+
156+ @ Configuration
157+ static class ConfigWithOverloadingAndAdditionalMetadata {
158+
159+ @ Bean @ Lazy
160+ String aString () {
161+ return "regular" ;
162+ }
163+
164+ @ Bean
165+ String aString (Integer dependency ) {
166+ return "overloaded" + dependency ;
167+ }
168+ }
169+
170+
125171 @ Configuration
126172 static class SuperConfig {
127173
@@ -140,7 +186,7 @@ Integer anInt() {
140186 return 5 ;
141187 }
142188
143- @ Bean
189+ @ Bean @ Lazy
144190 String aString (Integer dependency ) {
145191 return "overloaded" + dependency ;
146192 }
@@ -155,7 +201,7 @@ Integer anInt() {
155201 return 5 ;
156202 }
157203
158- @ Bean
204+ @ Bean @ Lazy
159205 String aString (List <Integer > dependency ) {
160206 return "overloaded" + dependency .get (0 );
161207 }
0 commit comments