如何在 Spring 中注入(自动装配)bean 以枚举作为映射键进行映射?

问题描述 投票:0回答:3

我了解到,在春天,我可以通过配置名称自动装配/注入到

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>
映射。有没有更好的解决方案来处理这个问题?还是我错过了什么?

java spring spring-boot dependency-injection autowired
3个回答
21
投票

您始终必须定义 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;
    }
}

在配置类中,您还可以验证每个组件是否声明唯一的非空枚举值。


0
投票

我知道这是一篇旧文章,但我多次使用了以下文章中的方法(或其变体):

https://medium.com/@pradumnkr98/dynamic-bean-injection-in-spring-how-to-select-beans-based-on-enum-values-ea290fdd4442


-3
投票

您必须添加

@Qualifier("impl1")
@Qualifier("impl2")
@Autowired
来注入您的实现类,因为
DummyInterface
有多个实现。

    @Autowired
    @Qualifier("impl2") //Injects impl2 class
    private EnumMap<Your Enum, DummyInterface> mapping;

更多关于

EnumMap
的信息,您可以参考这里

© www.soinside.com 2019 - 2024. All rights reserved.