Skip to content

Commit bf881e4

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 36a1d62 commit bf881e4

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
@@ -266,8 +266,16 @@ else if (candidate.getParameterTypes().length == 0) {
266266
}
267267
if (!candidates.isEmpty()) {
268268
// Add default constructor to list of optional constructors, as fallback.
269-
if (requiredConstructor == null && defaultConstructor != null) {
270-
candidates.add(defaultConstructor);
269+
if (requiredConstructor == null) {
270+
if (defaultConstructor != null) {
271+
candidates.add(defaultConstructor);
272+
}
273+
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
274+
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
275+
"': single autowire-marked constructor flagged as optional - this constructor " +
276+
"is effectively required since there is no default constructor to fall back to: " +
277+
candidates.get(0));
278+
}
271279
}
272280
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
273281
}

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

+33-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.beans.factory.BeanFactory;
3535
import org.springframework.beans.factory.FactoryBean;
3636
import org.springframework.beans.factory.ObjectFactory;
37+
import org.springframework.beans.factory.UnsatisfiedDependencyException;
3738
import org.springframework.beans.factory.config.BeanDefinition;
3839
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3940
import org.springframework.beans.factory.config.TypedStringValue;
@@ -549,6 +550,23 @@ public void testConstructorResourceInjectionWithMultipleCandidates() {
549550
bf.destroySingletons();
550551
}
551552

553+
@Test
554+
public void testConstructorResourceInjectionWithNoCandidatesAndNoFallback() {
555+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
556+
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
557+
bpp.setBeanFactory(bf);
558+
bf.addBeanPostProcessor(bpp);
559+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
560+
561+
try {
562+
bf.getBean("annotatedBean");
563+
fail("Should have thrown UnsatisfiedDependencyException");
564+
}
565+
catch (UnsatisfiedDependencyException ex) {
566+
// expected
567+
}
568+
}
569+
552570
@Test
553571
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
554572
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -2025,6 +2043,21 @@ public NestedTestBean[] getNestedTestBeans() {
20252043
}
20262044

20272045

2046+
public static class ConstructorWithoutFallbackBean {
2047+
2048+
protected ITestBean testBean3;
2049+
2050+
@Autowired(required = false)
2051+
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
2052+
this.testBean3 = testBean3;
2053+
}
2054+
2055+
public ITestBean getTestBean3() {
2056+
return this.testBean3;
2057+
}
2058+
}
2059+
2060+
20282061
public static class ConstructorsCollectionResourceInjectionBean {
20292062

20302063
protected ITestBean testBean3;
@@ -2090,7 +2123,6 @@ public static class MapFieldInjectionBean {
20902123
@Autowired
20912124
private Map<String, TestBean> testBeanMap;
20922125

2093-
20942126
public Map<String, TestBean> getTestBeanMap() {
20952127
return this.testBeanMap;
20962128
}

0 commit comments

Comments
 (0)