如何在Spring中将注入(自动装配)的bean与枚举作为Map键映射?
如何在Spring中将注入(自动装配)的bean与枚举作为Map键映射?
我了解到在春天,我可以按照下面的方式通过配置的名称将Map
自动装配/注入:
public interface DummyInterface{ } @Component("impl1") public class Impl1 implement DummyInterface{ } @Component("impl2") public class Impl2 implement DummyInterface{ } public class SomeUsage{ @Autowired private Mapmapping; // ... }
并且可以通过字符串作为键来获取Component
,例如:
SomeUsage use = new SomeUsage(); DummyInterface dummy = use.getMapping().get("impl1"); // do sth...
然而,如果bean映射的键不是String
类型,而是用户自定义的Enum
类型,那么我应该如何将bean注入到enumMap中呢?
我阅读了一些帖子并了解到它可以通过xml文件进行配置。但是看起来xml配置与
对紧密耦合,这意味着每次如果我添加一个新的
对,我都必须同步配置文件,这似乎与我的当前解决方案没有什么区别,即仍然使用
集合,并在Java代码中自己维护
映射。是否有更好的解决方案来处理这个问题?或者我错过了什么?
在Spring中,我们经常需要将枚举类与Spring Bean进行映射。但是,我们希望能够强制要求组件声明它们映射到哪个枚举值。为了实现这一点,我们可以创建一个接口EnumMappedBean,其中包含一个getSomeEnum方法,用来返回该组件映射的枚举值。
然后,我们需要让每个组件实现这个接口。例如,我们可以创建Bean1和Bean2类,它们分别实现了EnumMappedBean接口,并在getSomeEnum方法中返回相应的枚举值。
接下来,我们可以通过枚举值将每个组件进行映射。在AppConfig类中,我们可以定义一个方法getBeansMappedByEnum,该方法接收一个EnumMappedBean的集合,并将其转换成一个以枚举值为键、EnumMappedBean为值的Map。
然后,我们可以在需要的地方注入这个Map。例如,在SomeOtherBean类中,我们可以定义一个构造函数,接收这个Map作为参数。
需要注意的是,在配置类中,我们可以验证每个组件是否声明了唯一且非空的枚举值。
如果我们有一个Map
恐怕没有现成的解决方案来实现这一点。默认的依赖注入行为是基于bean的类型/名称的,无法通过简单地传递一些参数来更改它。
虽然我们可以使用按名称注入来处理这个问题,但这种方式需要所有使用该Bean的用户都按名称进行注入。只有在使用@Qualifier注解时,我们需要知道bean的名称。而使用@Autowired或@Inject注解时,我们可以根据类型或父类型获取受管实例。例如在上述代码中,SomeOtherBean对于配置类中的名称一无所知,依赖关系是根据是否存在Map
问题的出现的原因是在使用Spring的自动装配(autowired)功能时,当一个接口有多个实现类时,无法确定要注入哪个实现类。在这种情况下,需要使用限定符(qualifier)来指定要注入的实现类。
解决方法是在注入的字段上添加限定符,以指定要注入的实现类。在这个例子中,使用了一个枚举(Enum)作为Map的键,所以需要使用EnumMap来实现这个功能。
具体的解决方法如下:
@Qualifier("impl2") //注入impl2实现类 private EnumMapmapping;
当一个接口有多个实现类时,如果不添加限定符,Spring无法确定要注入哪个实现类。在注入实现类到Map中时,需要知道要注入的实现类的类型,在取出实现类时也需要知道要取出的是哪个实现类。
更多关于EnumMap的信息,可以参考[这里](https://stackoverflow.com/a/12669569/9092901)。
请检查注解的value字段,并参考[这里](https://stackoverflow.com/a/20180762/8510613)。