我了解到,在春天,我可以通过配置名称自动装配/注入到
Map<String, SomeBeanInterface>
,如下所示:
public interface DummyInterface{
}
@Component("impl1")
public class Impl1 implement DummyInterface{
}
@Component("impl2")
public class Impl2 implement DummyInterface{
}
public class SomeUsage{
@Autowired
private Map<String, DummyInterface> mapping;
// ...
}
并通过字符串作为键检索
Component
,例如:
SomeUsage use = new SomeUsage();
DummyInterface dummy = use.getMapping().get("impl1");
// do sth...
但是,如果bean映射的key不是
String
的类型,而是用户定义的Enum
的类型,我应该如何将bean注入到enumMap中?
我读过一些帖子,了解到它可以通过xml文件进行配置。但似乎xml配置与
<Enum, Bean>
对紧密耦合,这意味着每次如果我添加新的<Enum, Bean>
对,我都必须同步配置文件,似乎与我当前的解决方案,即仍然使用 <String, Bean>
集合并由我自己维护 java 代码中的 <Enum, String>
映射。有没有更好的解决方案来处理这个问题?还是我错过了什么?
您始终必须定义 Enum 和 Spring Bean 之间的映射,但您可以强制组件必须声明它们映射到哪个枚举。您可以实现这样的创建界面:
public interface EnumMappedBean {
SomeEnum getSomeEnum();
}
然后你想要映射的每个组件都必须实现它。
@Component
public class Bean1 implements EnumMappedBean {
@Override
public SomeEnum getSomeEnum() {
return SomeEnum.ENUM1;
}
}
@Component
public class Bean2 implements EnumMappedBean {
@Override
public SomeEnum getSomeEnum() {
return SomeEnum.ENUM2;
}
}
然后您可以通过其枚举来映射每个组件。
@Configuration
public class AppConfig {
@Bean
public Map<SomeEnum, EnumMappedBean> getBeansMappedByEnum(@NonNull Collection<EnumMappedBean> enumBeans) {
return enumBeans.stream()
.collect(toMap(EnumMappedBean::getSomeEnum, Function.identity()));
}
}
然后注射到任何你想要的地方。
@Service
public class SomeOtherBean {
private Map<SomeEnum, EnumMappedBean> beansMappedByEnum;
@Autowired
public SomeOtherBean(@NonNull Map<SomeEnum, EnumMappedBean> beansMappedByEnum) {
this.beansMappedByEnum = beansMappedByEnum;
}
}
在配置类中,您还可以验证每个组件是否声明唯一的非空枚举值。
我知道这是一篇旧文章,但我多次使用了以下文章中的方法(或其变体):
您必须添加
@Qualifier("impl1")
或 @Qualifier("impl2")
与 @Autowired
来注入您的实现类,因为 DummyInterface
有多个实现。
@Autowired
@Qualifier("impl2") //Injects impl2 class
private EnumMap<Your Enum, DummyInterface> mapping;
更多关于
EnumMap
的信息,您可以参考这里