Inject empty map via spring

2019-07-13 08:15发布

In my @Configuration file, I have beans with a relationship similar to the following:

@Bean
public Cache<Foo,Bar> fooBarCache(Map<Foo,Future<Bar>> refreshTaskMap) {
    return new AsyncUpdateCache(refreshTaskMap);
}

@Bean
public Map<Foo,Future<Bar>> refreshTaskMap() {
    return new HashMap<Foo,Future<Bar>>();
}

However, the ApplicationContext fails to load because it complains about "No qualifying bean of type [com.example.Bar]". From what I can tell, Spring is trying to be cute with creating a map for me and assumes I intend to use the map to lookup beans, or something similar.

How do I prevent it from trying to do its collection-injection "magic" and just inject the bean as I've declared it? I've tried adding a @Qualifier annotation on the fooBarCache argument, but that didn't seem to help.

1条回答
霸刀☆藐视天下
2楼-- · 2019-07-13 08:58

You can use another approach to bean dependency injection - invoking the bean factory method instead of taking it in as a parameter (Spring doc). Then your configuration would look like this:

@Bean
public Cache<Foo,Bar> fooBarCache() {
    return new AsyncUpdateCache(refreshTaskMap()); // call the method
}

@Bean
public Map<Foo,Future<Bar>> refreshTaskMap() {
    return new HashMap<Foo,Future<Bar>>();
}

Spring is smart enough to realize that you want to use the bean refreshTaskMap and not simply call the method and instead of creating a new and unmanaged map instance it will replace the call with a lookup of an existing refreshTaskMap bean. That is described further here.

If you intend to autowire refreshTaskMap in other beans (outside of this configuration class), the Springs semantics of @Autowire Map<String, V> is to autowire a map of all beans of the type V, where keys are the bean names (map key type must be String) (reference)

Even typed Maps can be autowired as long as the expected key type is String. The Map values will contain all beans of the expected type, and the keys will contain the corresponding bean names

In that case, you should use @Resource:

beans that are themselves defined as a collection or map type cannot be injected through @Autowired, because type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection or map bean by unique name.

查看更多
登录 后发表回答