首页 > 解决方案 > 如何在枚举构造函数中 @Autowire @Component`s?

问题描述

比方说,我有一个ProviderService带有Map<ProviderEnum, Provider>字段的类。那么这个类的构造函数如下

@Autowired
ProviderService(ProviderA provA, ProviderB provB, ...) {
    map.put(ProviderEnum.A, provA);
    map.put(ProviderEnum.B, provB);
    ...
}

Provider是一个抽象类继承者,它的注释用@Component.
然后我意识到至少有两种可能更好的方法来做到这一点:

  1. 用于EnumMap执行Map. 现在,我使用HashMap.
  2. 枚举中有一个Provider字段并完全删除地图。 ProviderEnumProviderService

第二个选项似乎是更清洁的解决方案,我开始这样写

enum ProviderEnum {
    A(/* ?WHAT DO I PUT HERE? */),
    B(/* Is it some kind of BeanFactory.getBean(ProviderB.class)? */),
    ...;

    private final Provider provider;
    
    ProviderEnum(Provider provider) {
        this.provider = provider;
    }
    
    public Provider getProvider() {
        return this.provider;
    }    
}

但是,我不知道应该在这些构造函数中放入什么,因为它肯定与使用@Autowired.
我想我应该考虑使用BeanFactory但是有没有办法构造函数注入它?我应该现场注入它吗?还是坚持下去更好EnumMap

标签: javaspringdependency-injectionenumsautowired

解决方案


枚举是静态的,imo 更好的方法是将类型的集合自动装配到您的服务中,就像这样

  1. 提供者接口(或你如何看待它)
public interface Provider {
    // This can be your differentiator
    ProviderEnum getProviderType();
    void doSomeProviderThing();    
}
  1. 在您的 ProviderService 类中,您可以自动装配一个集合并使用 PostConstruct 来完成其余的工作
@Component
public class ProviderService {

    // This will autowire all providers as a collection
    @Autowired
    private  Collection<Provider> providers;
 
    @PostConstruct
    public void init() {
        providers.stream().foreach( provider -> {
            // Do you mapping with provider.getProviderType() if you still see value.
            // like map.put(provider.getProviderType(), provider);
        }); 
    }

}

推荐阅读