@Configuration
public class Config {
@Bean
Object mapConfigDemo1(@Qualifier("sampleMap1") HashMap<String, Object> hashMap) {
System.out.println("map1: "+hashMap.entrySet().stream().map(Objects::toString).collect(Collectors.joining(",")));
return hashMap.get("key");
}
@Bean
HashMap<String, Object> sampleMap1() {
return new HashMap<>() {
{
put("key", "1");
}
};
}
@Bean
Object mapConfigDemo2(@Qualifier("sampleMap2") Map<String, String> hashMap) {
System.out.println("map2: "+hashMap.entrySet().stream().map(Objects::toString).collect(Collectors.joining(",")));
return hashMap.get("key");
}
@Bean
Map<String, String> sampleMap2() {
return new HashMap<>() {
{
put("key", "2");
}
};
}
@Bean
Object mapConfigDemo3(@Qualifier("sampleMap3") Map<String, Object> hashMap) {
System.out.println("map3: "+hashMap.entrySet().stream().map(Objects::toString).collect(Collectors.joining(",")));
return hashMap.get("key");
}
@Bean
Map<String, Object> sampleMap3() {
return new HashMap<>() {
{
put("key", "3");
}
};
}
}
I would have expected that the console output would be:
map1: key=1
map2: key=2
map3: key=3
Actually the console output is:
map1: key=1
map2: key=2
map3: sampleMap3={key=3}
Comment From: sbrannen
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Comment From: snicoll
In general, you should not expose beans of type Map
or List
as the core container has special handling for this types (gathering a mapping from bean name to bean, and collection the beans of a certain type).
@Qualifier
doesn't act as bean-name semantic as you seem to be using it. It really is a by-type injection with an additional hint in case of multiple by-type candidates. And the Map<String,?>
is the framework really trying to do the best it can with what you're asking. The target will be mapped to another map of bean name to type.
I can see how that's surprising, but there's nothing we can do without breaking something else. Use dedicated types to wrap beans like that.