Description
Sotirios Delimanolis opened SPR-15117 and commented
This issue follows the findings in this Stack Overflow question.
Consider the following
@Component
class TestControl {
@Autowired
public TestControl(BiMap<String, Integer> parameter) { }
}
@Configuration
public class Example {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Example.class, TestControl.class);
}
@Bean
BiMap<String, Integer> someBiMap() {
return ImmutableBiMap.of("some key", someFoo());
}
@Bean
Integer someFoo() {
return 6;
}
}
The expect behavior is for the bean named someBiMap
to be injected in the TestControl
constructor.
Instead, we get a BeanInstantiationException
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.TestControl]: Illegal arguments for constructor; nested exception is java.lang.IllegalArgumentException: argument type mismatch
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:158)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:267)
... 13 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 15 more
We can work around this by qualifying the parameter name
public TestControl(@Qualifier("someBiMap") BiMap<String, Integer> parameter) {}
or using using field injection with @Resource
and the appropriate name, assuming the field is non-final
.
However, the documentation states
That said, as of 4.3, collection/map and array types can be matched through Spring’s
@Autowired
type matching algorithm as well, as long as the element type information is preserved in@Bean
return type signatures or collection inheritance hierarchies.
which makes me think this is a bug. The resolution for a Map
of bean names to beans seems to take precedence over the resolution by type.
Affects: 4.3.2
Issue Links:
- Optional autowire of Map<String, BeanType> accidentally falls back to unrelated Map<String, String> [SPR-13963] #18536 Optional autowire of Map<String, BeanType> accidentally falls back to unrelated Map<String, String>
- Allow for normal bean wiring semantics for types assignable to Map [SPR-7915] #12570 Allow for normal bean wiring semantics for types assignable to Map