Mario Zagar opened SPR-15940 and commented
Using: - spring-framework 5.0.0.RC3 (also tested wth 1.5.6.RELEASE, problem also present) - kotlin-stdlib 1.1.4-3
Following test fails when autowiring kotlin Collection @Autowired
lateinit var beans : Collection
When using java.util.Collection autowiring works as expected.
Not really sure if this is kotlin issue or spring issue.
Here's the test:
package spring.autowire.test
import org.assertj.core.api.Assertions
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringRunner
interface FirstInterface
interface SecondInterface
interface ThirdInterface
class Bean1 : FirstInterface, SecondInterface, ThirdInterface
class Bean2 : FirstInterface, SecondInterface, ThirdInterface
class Bean3 : FirstInterface, SecondInterface, ThirdInterface
class Bean4 : FirstInterface, SecondInterface, ThirdInterface
@Configuration
open class TestSpringConfig {
@Bean open fun bean1() : Bean1 = Bean1()
@Bean open fun bean2() : FirstInterface = Bean2()
@Bean open fun bean3() : SecondInterface = Bean3();
@Bean open fun bean4() : ThirdInterface = Bean4();
}
@RunWith(SpringRunner::class)
@ContextConfiguration(classes = arrayOf(TestSpringConfig::class))
class KotlinAutowireTest {
@Autowired
lateinit var beans : Collection<SecondInterface> // test passes if I use java.util.Collection<SecondInterface>
@Test
fun test() {
Assertions.assertThat(beans)
.extracting{it.javaClass.name}
.containsOnly(
"spring.autowire.test.Bean1",
"spring.autowire.test.Bean2",
"spring.autowire.test.Bean3",
"spring.autowire.test.Bean4"
)
}
}
Test output:
java.lang.AssertionError:
Expecting:
<["spring.autowire.test.Bean1", "spring.autowire.test.Bean3"]>
to contain only:
<["spring.autowire.test.Bean1",
"spring.autowire.test.Bean2",
"spring.autowire.test.Bean3",
"spring.autowire.test.Bean4"]>
but could not find the following elements:
<["spring.autowire.test.Bean2", "spring.autowire.test.Bean4"]>
Affects: 5.0 RC3
1 votes, 3 watchers
Comment From: spring-projects-issues
Sébastien Deleuze commented
I had a look to this repro test and found that MutableCollection
is working as expected while indeed Collection
(the Kotlin one) ones returns 2 beans. After comparing both cases, I found that the difference of behavior comes from GenericTypeAwareAutowireCandidateResolver#checkGenericTypeMatch
which could behave differently because of Kotlin declaration-site variance:
- Collection
is declared as interface Collection<out E>
- MutableCollection
is declared as interface MutableCollection<E>
Juergen Hoeller I have added a unit test in this branch to compare Kotlin MutableCollection
and Collection
, do you have any thoughts about this behavior being related to our generics comparison algorythm having to be tuned to support Kotlin declaration-site variance or if the issue could be on Kotlin side?
Comment From: sdeleuze
Duplicate of #22313.