Skip to content

Commit 5da8a16

Browse files
committed
AbstractAutowireCapableBeanFactory avoids early FactoryBean instantiation on currently created configuration bean
Issue: SPR-12141 (cherry picked from commit 4432c41)
1 parent 3b64db1 commit 5da8a16

File tree

3 files changed

+89
-45
lines changed

3 files changed

+89
-45
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,8 @@ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, Root
795795
if (bw != null) {
796796
return (FactoryBean<?>) bw.getWrappedInstance();
797797
}
798-
if (isSingletonCurrentlyInCreation(beanName)) {
798+
if (isSingletonCurrentlyInCreation(beanName) ||
799+
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
799800
return null;
800801
}
801802
Object instance = null;

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

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,12 +17,9 @@
1717
package org.springframework.context.annotation;
1818

1919
import org.junit.Test;
20-
import org.springframework.beans.factory.BeanCreationException;
20+
2121
import org.springframework.beans.factory.FactoryBean;
2222
import org.springframework.beans.factory.annotation.Autowired;
23-
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
24-
import org.springframework.context.annotation.Bean;
25-
import org.springframework.context.annotation.Configuration;
2623
import org.springframework.util.Assert;
2724

2825
/**
@@ -35,58 +32,51 @@ public class ConfigurationWithFactoryBeanAndAutowiringTests {
3532

3633
@Test
3734
public void withConcreteFactoryBeanImplementationAsReturnType() {
38-
AnnotationConfigApplicationContext ctx =
39-
new AnnotationConfigApplicationContext();
35+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
4036
ctx.register(AppConfig.class);
4137
ctx.register(ConcreteFactoryBeanImplementationConfig.class);
4238
ctx.refresh();
4339
}
4440

4541
@Test
4642
public void withParameterizedFactoryBeanImplementationAsReturnType() {
47-
AnnotationConfigApplicationContext ctx =
48-
new AnnotationConfigApplicationContext();
43+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
4944
ctx.register(AppConfig.class);
5045
ctx.register(ParameterizedFactoryBeanImplementationConfig.class);
5146
ctx.refresh();
5247
}
5348

5449
@Test
5550
public void withParameterizedFactoryBeanInterfaceAsReturnType() {
56-
AnnotationConfigApplicationContext ctx =
57-
new AnnotationConfigApplicationContext();
51+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
5852
ctx.register(AppConfig.class);
5953
ctx.register(ParameterizedFactoryBeanInterfaceConfig.class);
6054
ctx.refresh();
6155
}
6256

6357
@Test
6458
public void withNonPublicParameterizedFactoryBeanInterfaceAsReturnType() {
65-
AnnotationConfigApplicationContext ctx =
66-
new AnnotationConfigApplicationContext();
59+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
6760
ctx.register(AppConfig.class);
6861
ctx.register(NonPublicParameterizedFactoryBeanInterfaceConfig.class);
6962
ctx.refresh();
7063
}
7164

72-
@Test(expected=BeanCreationException.class)
65+
@Test
7366
public void withRawFactoryBeanInterfaceAsReturnType() {
74-
AnnotationConfigApplicationContext ctx =
75-
new AnnotationConfigApplicationContext();
67+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
7668
ctx.register(AppConfig.class);
7769
ctx.register(RawFactoryBeanInterfaceConfig.class);
7870
ctx.refresh();
7971
}
8072

81-
@Test(expected=BeanCreationException.class)
73+
@Test
8274
public void withWildcardParameterizedFactoryBeanInterfaceAsReturnType() {
83-
AnnotationConfigApplicationContext ctx =
84-
new AnnotationConfigApplicationContext();
75+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
8576
ctx.register(AppConfig.class);
8677
ctx.register(WildcardParameterizedFactoryBeanInterfaceConfig.class);
8778
ctx.refresh();
8879
}
89-
9080
}
9181

9282

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

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,29 +16,36 @@
1616

1717
package org.springframework.context.annotation;
1818

19-
import static org.hamcrest.CoreMatchers.equalTo;
20-
import static org.hamcrest.CoreMatchers.is;
21-
import static org.junit.Assert.assertThat;
22-
import static org.junit.Assert.assertTrue;
23-
19+
import java.io.FileNotFoundException;
2420
import java.util.Iterator;
25-
2621
import javax.inject.Inject;
2722

23+
import org.junit.Rule;
2824
import org.junit.Test;
25+
import org.junit.rules.ExpectedException;
26+
27+
import org.springframework.beans.factory.BeanDefinitionStoreException;
28+
import org.springframework.beans.factory.FactoryBean;
2929
import org.springframework.core.env.Environment;
3030
import org.springframework.core.env.MutablePropertySources;
31-
3231
import org.springframework.tests.sample.beans.TestBean;
3332

33+
import static org.hamcrest.CoreMatchers.*;
34+
import static org.junit.Assert.*;
35+
3436
/**
3537
* Tests the processing of @PropertySource annotations on @Configuration classes.
3638
*
3739
* @author Chris Beams
40+
* @author Phillip Webb
3841
* @since 3.1
3942
*/
4043
public class PropertySourceAnnotationTests {
4144

45+
@Rule
46+
public ExpectedException thrown = ExpectedException.none();
47+
48+
4249
@Test
4350
public void withExplicitName() {
4451
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@@ -93,7 +100,7 @@ public void orderingIsLifo() {
93100
}
94101
}
95102

96-
@Test(expected=IllegalArgumentException.class)
103+
@Test(expected = IllegalArgumentException.class)
97104
public void withUnresolvablePlaceholder() {
98105
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
99106
ctx.register(ConfigWithUnresolvablePlaceholder.class);
@@ -118,21 +125,24 @@ public void withResolvablePlaceholder() {
118125
System.clearProperty("path.to.properties");
119126
}
120127

121-
/**
122-
* Corner bug reported in SPR-9127.
123-
*/
124128
@Test
125-
public void withNameAndMultipleResourceLocations() {
129+
public void withResolvablePlaceholderAndFactoryBean() {
126130
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
127-
ctx.register(ConfigWithNameAndMultipleResourceLocations.class);
131+
ctx.register(ConfigWithResolvablePlaceholderAndFactoryBean.class);
132+
System.setProperty("path.to.properties", "org/springframework/context/annotation");
128133
ctx.refresh();
129-
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
130-
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
134+
assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p1TestBean"));
135+
System.clearProperty("path.to.properties");
131136
}
132137

133-
/**
134-
* SPR-10820
135-
*/
138+
@Test(expected = IllegalArgumentException.class)
139+
public void withEmptyResourceLocations() {
140+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
141+
ctx.register(ConfigWithEmptyResourceLocations.class);
142+
ctx.refresh();
143+
}
144+
145+
// SPR-10820
136146
@Test
137147
public void orderingWithAndWithoutNameAndMultipleResourceLocations() {
138148
// p2 should 'win' as it was registered last
@@ -142,11 +152,22 @@ public void orderingWithAndWithoutNameAndMultipleResourceLocations() {
142152
assertThat(ctxWithName.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
143153
}
144154

145-
@Test(expected=IllegalArgumentException.class)
146-
public void withEmptyResourceLocations() {
147-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
148-
ctx.register(ConfigWithEmptyResourceLocations.class);
149-
ctx.refresh();
155+
@Test
156+
public void withNameAndMultipleResourceLocations() {
157+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNameAndMultipleResourceLocations.class);
158+
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
159+
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
160+
// p2 should 'win' as it was registered last
161+
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
162+
}
163+
164+
@Test
165+
public void withMultipleResourceLocations() {
166+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithMultipleResourceLocations.class);
167+
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
168+
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
169+
// p2 should 'win' as it was registered last
170+
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
150171
}
151172

152173

@@ -159,6 +180,7 @@ static class ConfigWithUnresolvablePlaceholder {
159180
@Configuration
160181
@PropertySource(value="classpath:${unresolvable:org/springframework/context/annotation}/p1.properties")
161182
static class ConfigWithUnresolvablePlaceholderAndDefault {
183+
162184
@Inject Environment env;
163185

164186
@Bean
@@ -171,6 +193,7 @@ public TestBean testBean() {
171193
@Configuration
172194
@PropertySource(value="classpath:${path.to.properties}/p1.properties")
173195
static class ConfigWithResolvablePlaceholder {
196+
174197
@Inject Environment env;
175198

176199
@Bean
@@ -180,10 +203,37 @@ public TestBean testBean() {
180203
}
181204

182205

206+
@Configuration
207+
@PropertySource(value="classpath:${path.to.properties}/p1.properties")
208+
static class ConfigWithResolvablePlaceholderAndFactoryBean {
209+
210+
@Inject Environment env;
211+
212+
@Bean
213+
public FactoryBean testBean() {
214+
final String name = env.getProperty("testbean.name");
215+
return new FactoryBean() {
216+
@Override
217+
public Object getObject() {
218+
return new TestBean(name);
219+
}
220+
@Override
221+
public Class<?> getObjectType() {
222+
return TestBean.class;
223+
}
224+
@Override
225+
public boolean isSingleton() {
226+
return false;
227+
}
228+
};
229+
}
230+
}
231+
183232

184233
@Configuration
185234
@PropertySource(name="p1", value="classpath:org/springframework/context/annotation/p1.properties")
186235
static class ConfigWithExplicitName {
236+
187237
@Inject Environment env;
188238

189239
@Bean
@@ -196,6 +246,7 @@ public TestBean testBean() {
196246
@Configuration
197247
@PropertySource("classpath:org/springframework/context/annotation/p1.properties")
198248
static class ConfigWithImplicitName {
249+
199250
@Inject Environment env;
200251

201252
@Bean
@@ -221,6 +272,7 @@ static class P2Config {
221272
static class ConfigWithNameAndMultipleResourceLocations {
222273
}
223274

275+
224276
@Configuration
225277
@PropertySource(
226278
value = {
@@ -235,4 +287,5 @@ static class ConfigWithMultipleResourceLocations {
235287
@PropertySource(value = {})
236288
static class ConfigWithEmptyResourceLocations {
237289
}
290+
238291
}

0 commit comments

Comments
 (0)