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

use*_*613 6 java spring dependency-injection autowired spring-boot

我了解到在 spring 中,我可以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;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

并检索Componentby 字符串作为键,如:

SomeUsage use = new SomeUsage();
DummyInterface dummy = use.getMapping().get("impl1");
// do sth...
Run Code Online (Sandbox Code Playgroud)

但是,如果bean映射的关键不是的类型String,而是用户定义的类型Enum,我应该如何将bean注入到enumMap中?

我读过一些帖子,了解到它可以通过 xml 文件进行配置。但是好像是xml配置和<Enum, Bean>pair是紧耦合的,这意味着每次如果我添加一个新<Enum, Bean>对,我必须同步配置文件,与我当前的解决方案相比似乎没有区别,那就是,仍然使用<String, Bean>集合<Enum, String>并由我自己在java代码中维护映射。有没有更好的解决方案来处理这个问题?或者我错过了什么?

kem*_*t90 12

您总是必须定义 Enum 和 Spring Bean 之间的映射,但您可以强制组件必须声明它们映射到的枚举。您可以实现创建界面,如:

public interface EnumMappedBean {
    SomeEnum getSomeEnum();
}
Run Code Online (Sandbox Code Playgroud)

然后,您要映射的每个组件都必须实现它。

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以通过它的枚举来映射每个组件。

@Configuration
public class AppConfig {
    @Bean
    public Map<SomeEnum, EnumMappedBean> getBeansMappedByEnum(@NonNull Collection<EnumMappedBean> enumBeans) {
        return enumBeans.stream()
                .collect(toMap(EnumMappedBean::getSomeEnum, Function.identity()));
    }
}
Run Code Online (Sandbox Code Playgroud)

并在您想要的任何地方注入。

@Service
public class SomeOtherBean {

    private Map<SomeEnum, EnumMappedBean> beansMappedByEnum;

    @Autowired
    public SomeOtherBean(@NonNull Map<SomeEnum, EnumMappedBean> beansMappedByEnum) {
        this.beansMappedByEnum = beansMappedByEnum;
    }
}
Run Code Online (Sandbox Code Playgroud)

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