Skip to content

Commit 5cf4524

Browse files
committed
Log warning for single optional constructor when no default constructor to fall back to
Issue: SPR-12161 (cherry picked from commit 80cec01)
1 parent e819999 commit 5cf4524

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,16 @@ else if (candidate.getParameterTypes().length == 0) {
263263
}
264264
if (!candidates.isEmpty()) {
265265
// Add default constructor to list of optional constructors, as fallback.
266-
if (requiredConstructor == null && defaultConstructor != null) {
267-
candidates.add(defaultConstructor);
266+
if (requiredConstructor == null) {
267+
if (defaultConstructor != null) {
268+
candidates.add(defaultConstructor);
269+
}
270+
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
271+
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
272+
"': single autowire-marked constructor flagged as optional - this constructor " +
273+
"is effectively required since there is no default constructor to fall back to: " +
274+
candidates.get(0));
275+
}
268276
}
269277
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
270278
}

spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

+33-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.beans.factory.BeanFactory;
3131
import org.springframework.beans.factory.FactoryBean;
3232
import org.springframework.beans.factory.ObjectFactory;
33+
import org.springframework.beans.factory.UnsatisfiedDependencyException;
3334
import org.springframework.beans.factory.config.BeanDefinition;
3435
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3536
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
@@ -395,6 +396,23 @@ public void testConstructorResourceInjectionWithMultipleCandidates() {
395396
bf.destroySingletons();
396397
}
397398

399+
@Test
400+
public void testConstructorResourceInjectionWithNoCandidatesAndNoFallback() {
401+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
402+
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
403+
bpp.setBeanFactory(bf);
404+
bf.addBeanPostProcessor(bpp);
405+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
406+
407+
try {
408+
bf.getBean("annotatedBean");
409+
fail("Should have thrown UnsatisfiedDependencyException");
410+
}
411+
catch (UnsatisfiedDependencyException ex) {
412+
// expected
413+
}
414+
}
415+
398416
@Test
399417
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
400418
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -1256,6 +1274,21 @@ public NestedTestBean[] getNestedTestBeans() {
12561274
}
12571275

12581276

1277+
public static class ConstructorWithoutFallbackBean {
1278+
1279+
protected ITestBean testBean3;
1280+
1281+
@Autowired(required = false)
1282+
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
1283+
this.testBean3 = testBean3;
1284+
}
1285+
1286+
public ITestBean getTestBean3() {
1287+
return this.testBean3;
1288+
}
1289+
}
1290+
1291+
12591292
public static class ConstructorsCollectionResourceInjectionBean {
12601293

12611294
protected ITestBean testBean3;
@@ -1321,7 +1354,6 @@ public static class MapFieldInjectionBean {
13211354
@Autowired
13221355
private Map<String, TestBean> testBeanMap;
13231356

1324-
13251357
public Map<String, TestBean> getTestBeanMap() {
13261358
return this.testBeanMap;
13271359
}

0 commit comments

Comments
 (0)