Log warning for single optional constructor when no default constructor to fall back to
Issue: SPR-12161
This commit is contained in:
@@ -299,8 +299,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||||||
}
|
}
|
||||||
if (!candidates.isEmpty()) {
|
if (!candidates.isEmpty()) {
|
||||||
// Add default constructor to list of optional constructors, as fallback.
|
// Add default constructor to list of optional constructors, as fallback.
|
||||||
if (requiredConstructor == null && defaultConstructor != null) {
|
if (requiredConstructor == null) {
|
||||||
candidates.add(defaultConstructor);
|
if (defaultConstructor != null) {
|
||||||
|
candidates.add(defaultConstructor);
|
||||||
|
}
|
||||||
|
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
|
||||||
|
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
|
||||||
|
"': single autowire-marked constructor flagged as optional - this constructor " +
|
||||||
|
"is effectively required since there is no default constructor to fall back to: " +
|
||||||
|
candidates.get(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
|||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
|
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.config.TypedStringValue;
|
import org.springframework.beans.factory.config.TypedStringValue;
|
||||||
@@ -52,7 +53,6 @@ import org.springframework.tests.sample.beans.TestBean;
|
|||||||
import org.springframework.util.SerializationTestUtils;
|
import org.springframework.util.SerializationTestUtils;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
@@ -552,6 +552,23 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
|||||||
bf.destroySingletons();
|
bf.destroySingletons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructorResourceInjectionWithNoCandidatesAndNoFallback() {
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||||
|
bpp.setBeanFactory(bf);
|
||||||
|
bf.addBeanPostProcessor(bpp);
|
||||||
|
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
|
||||||
|
|
||||||
|
try {
|
||||||
|
bf.getBean("annotatedBean");
|
||||||
|
fail("Should have thrown UnsatisfiedDependencyException");
|
||||||
|
}
|
||||||
|
catch (UnsatisfiedDependencyException ex) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
|
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
|
||||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
@@ -2048,6 +2065,21 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class ConstructorWithoutFallbackBean {
|
||||||
|
|
||||||
|
protected ITestBean testBean3;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
|
||||||
|
this.testBean3 = testBean3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITestBean getTestBean3() {
|
||||||
|
return this.testBean3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ConstructorsCollectionResourceInjectionBean {
|
public static class ConstructorsCollectionResourceInjectionBean {
|
||||||
|
|
||||||
protected ITestBean testBean3;
|
protected ITestBean testBean3;
|
||||||
@@ -2113,7 +2145,6 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private Map<String, TestBean> testBeanMap;
|
private Map<String, TestBean> testBeanMap;
|
||||||
|
|
||||||
|
|
||||||
public Map<String, TestBean> getTestBeanMap() {
|
public Map<String, TestBean> getTestBeanMap() {
|
||||||
return this.testBeanMap;
|
return this.testBeanMap;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user