From fb09a75c8229a440dd302c3585853b967f0dcba3 Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Wed, 27 Sep 2017 11:10:22 +0200 Subject: [PATCH] Improve support of Kotlin beans w/ primary and default ctors This commit add the default constructor if available as fallback after to the primary constructor. Issue: SPR-16012 --- .../AutowiredAnnotationBeanPostProcessor.java | 4 ++- .../annotation/KotlinAutowiredTests.kt | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) 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()) + } + }