Skip to content

Commit fb09a75

Browse files
committed
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
1 parent ec5969c commit fb09a75

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,9 @@ else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0)
367367
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
368368
}
369369
else if (kotlinPrimaryConstructor != null) {
370-
candidateConstructors = new Constructor<?>[] {kotlinPrimaryConstructor};
370+
candidateConstructors = (defaultConstructor != null ?
371+
new Constructor<?>[] {kotlinPrimaryConstructor, defaultConstructor} :
372+
new Constructor<?>[] {kotlinPrimaryConstructor});
371373
}
372374
else {
373375
candidateConstructors = new Constructor<?>[0];

spring-beans/src/test/kotlin/org/springframework/beans/factory/annotation/KotlinAutowiredTests.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,36 @@ class KotlinAutowiredTests {
122122
assertSame(colour, kb.injectedFromSecondaryConstructor)
123123
}
124124

125+
@Test // SPR-16012
126+
fun `Fallback on the default constructor when no autowirable primary constructor is defined`() {
127+
val bf = DefaultListableBeanFactory()
128+
val bpp = AutowiredAnnotationBeanPostProcessor()
129+
bpp.setBeanFactory(bf)
130+
bf.addBeanPostProcessor(bpp)
131+
val bd = RootBeanDefinition(KotlinBeanWithPrimaryAndDefaultConstructors::class.java)
132+
bd.scope = RootBeanDefinition.SCOPE_PROTOTYPE
133+
bf.registerBeanDefinition("bean", bd)
134+
135+
val kb = bf.getBean("bean", KotlinBeanWithPrimaryAndDefaultConstructors::class.java)
136+
assertNotNull(kb.testBean)
137+
}
138+
139+
@Test // SPR-16012
140+
fun `Instantiation via primary constructor when a default is defined`() {
141+
val bf = DefaultListableBeanFactory()
142+
val bpp = AutowiredAnnotationBeanPostProcessor()
143+
bpp.setBeanFactory(bf)
144+
bf.addBeanPostProcessor(bpp)
145+
val bd = RootBeanDefinition(KotlinBeanWithPrimaryAndDefaultConstructors::class.java)
146+
bd.scope = RootBeanDefinition.SCOPE_PROTOTYPE
147+
bf.registerBeanDefinition("bean", bd)
148+
val tb = TestBean()
149+
bf.registerSingleton("testBean", tb)
150+
151+
val kb = bf.getBean("bean", KotlinBeanWithPrimaryAndDefaultConstructors::class.java)
152+
assertEquals(tb, kb.testBean)
153+
}
154+
125155

126156
class KotlinBean(val injectedFromConstructor: TestBean?) {
127157

@@ -163,4 +193,9 @@ class KotlinAutowiredTests {
163193
var injectedFromSecondaryConstructor: Colour? = null
164194
}
165195

196+
@Suppress("unused")
197+
class KotlinBeanWithPrimaryAndDefaultConstructors(val testBean: TestBean) {
198+
constructor() : this(TestBean())
199+
}
200+
166201
}

0 commit comments

Comments
 (0)