diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 97b73f1119..3cb69ffee8 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -367,7 +367,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean candidateConstructors = new Constructor[] {rawCandidates[0]}; } else if (kotlinPrimaryConstructor != null) { - candidateConstructors = new Constructor[] {kotlinPrimaryConstructor}; + candidateConstructors = (defaultConstructor != null ? + new Constructor[] {kotlinPrimaryConstructor, defaultConstructor} : + new Constructor[] {kotlinPrimaryConstructor}); } else { candidateConstructors = new Constructor[0]; diff --git a/spring-beans/src/test/kotlin/org/springframework/beans/factory/annotation/KotlinAutowiredTests.kt b/spring-beans/src/test/kotlin/org/springframework/beans/factory/annotation/KotlinAutowiredTests.kt index e64100c650..b8e05974fc 100644 --- a/spring-beans/src/test/kotlin/org/springframework/beans/factory/annotation/KotlinAutowiredTests.kt +++ b/spring-beans/src/test/kotlin/org/springframework/beans/factory/annotation/KotlinAutowiredTests.kt @@ -122,6 +122,36 @@ class KotlinAutowiredTests { assertSame(colour, kb.injectedFromSecondaryConstructor) } + @Test // SPR-16012 + fun `Fallback on the default constructor when no autowirable primary constructor is defined`() { + val bf = DefaultListableBeanFactory() + val bpp = AutowiredAnnotationBeanPostProcessor() + bpp.setBeanFactory(bf) + bf.addBeanPostProcessor(bpp) + val bd = RootBeanDefinition(KotlinBeanWithPrimaryAndDefaultConstructors::class.java) + bd.scope = RootBeanDefinition.SCOPE_PROTOTYPE + bf.registerBeanDefinition("bean", bd) + + val kb = bf.getBean("bean", KotlinBeanWithPrimaryAndDefaultConstructors::class.java) + assertNotNull(kb.testBean) + } + + @Test // SPR-16012 + fun `Instantiation via primary constructor when a default is defined`() { + val bf = DefaultListableBeanFactory() + val bpp = AutowiredAnnotationBeanPostProcessor() + bpp.setBeanFactory(bf) + bf.addBeanPostProcessor(bpp) + val bd = RootBeanDefinition(KotlinBeanWithPrimaryAndDefaultConstructors::class.java) + bd.scope = RootBeanDefinition.SCOPE_PROTOTYPE + bf.registerBeanDefinition("bean", bd) + val tb = TestBean() + bf.registerSingleton("testBean", tb) + + val kb = bf.getBean("bean", KotlinBeanWithPrimaryAndDefaultConstructors::class.java) + assertEquals(tb, kb.testBean) + } + class KotlinBean(val injectedFromConstructor: TestBean?) { @@ -163,4 +193,9 @@ class KotlinAutowiredTests { var injectedFromSecondaryConstructor: Colour? = null } + @Suppress("unused") + class KotlinBeanWithPrimaryAndDefaultConstructors(val testBean: TestBean) { + constructor() : this(TestBean()) + } + }