如果我的术语混乱,我很抱歉,我对Spring很新。
我继承了一个具有相当不吸引人的方法的应用程序,如下所示:
该应用处理3种类型的数据(T1, T2, T3
)。类型位于枚举类DataType
。
有一个数据服务类层次结构,带有抽象的DataService类,还有3个派生类(每个DataType一个)T1DataService,T2DataService ....
配置为数据服务创建3个bean:
@Bean(name = "T1DataService")
public DataService getDataService() throws Exception {
return new T1DataService();
}
@Bean(name = "T2DataService")
public DataService getDataService() throws Exception {
return new T2DataService();
}
@Bean(name = "T3DataService")
public DataService getDataService() throws Exception {
return new T3DataService();
}
类似地,有一个计算服务,只有1个类,但有3个bean实例,其中数据类型被传递给每个实例的构造函数:
@Bean(name = "T1ComputeService")
public ComputeService getComputeService() throws Exception {
return new ComputeService (T1);
}
@Bean(name = "T2ComputeService")
public ComputeService getComputeService() throws Exception {
return new ComputeService (T2);
}
@Bean(name = "T3ComputeService")
public ComputeService getComputeService() throws Exception {
return new ComputeService (T3);
}
有一个请求处理器类,它需要来自DataService的数据,以及来自ComputeService的计算,基于请求中指定的数据类型。
它的编码方式是Autowire所有3个数据和3个计算服务bean:
@Autowired @Qualifier("T1DataService")
protected DataService T1DataService;
@Autowired @Qualifier("T2DataService")
protected DataService T2DataService;
@Autowired @Qualifier("T3DataService")
protected DataService T3DataService;
@Autowired @Qualifier("T1ComputeService")
protected ComputeService T1ComputeService;
@Autowired @Qualifier("T2ComputeService")
protected ComputeService T2ComputeService;
@Autowired @Qualifier("T3ComputeService")
protected ComputeService T3ComputeService;
然后,在处理器类的代码中:
DataService dataService = null;
ComputeService computeService = null;
switch (request.dataType) {
case T1:
dataService = T1DataService;
computeService = T1ComputeService;
break;
case T2:
dataService = T2DataService;
computeService = T2ComputeService;
break;
case T3:
dataService = T3DataService;
computeService = T3ComputeService;
break;
这似乎是一种非常糟糕的选择正确对象的方式。
如果这些不是自动装配的Spring bean,而是常规的POJO,我会简单地将它们隐藏在HashMap中
static HashMap<DataType, DataService> dataServices = new HashMap<>();
dataServices.put(T1, new T1DataService());
dataServices.put(T2, new T2DataService());
dataServices.put(T3, new T3DataService());
static HashMap<DataType, ComputeService> computeServices = new HashMap<>();
for (DataType dataType : DataType.allDataTypes()) {
computeServices.put(dataType , new ComputeService(dataType));
}
...然后在处理器类中,通过密钥从HashMap获取它来访问正确的服务对象:
DataService dataService = dataServices.get(request.dataType);
ComputeService computeService = computeServices.get(request.dataType);
答案 0 :(得分:0)
我会将bean名称或类放在枚举中并使用ApplicationContext#getBean(使用lombok annotations):
@RequiredArgsConstructor
enum DataType {
T1("T1DataService", "T1ComputeService"),
T2("T2DataService", "T2ComputeService"),
T3("T3DataService", "T3ComputeService");
@Getter
private final String dataServiceName;
@Getter
private final String computeServiceName;
}
然后
DataService dataService = applicationContext.getBean(DataType.T1.getDataServiceName());
ComputeService computeService = applicationContext.getBean(DataType.T1.getComputeServiceName());
(类似的情况,请注意您也可以假设bean名称已规范化并执行DataType.T1.name() + "DataService"
)
答案 1 :(得分:0)
这里有一些事情需要发生:
你可以从applicationContext中获取东西,但imo会向后退一步,远离基于注释的配置。
说到ComputeService
,是否真的有必要将枚举常量作为状态引入?如果这可以推广,而是检查类'方法的哪个枚举常量参数成立,那么你可以只使用这个类的一个实例。
然后,你会有这样的事情:
public class Something {
@Inject
private ComputeService computeService;
@Inject
@Named("T1DataService")
private DataService T1DataService;
@Inject
@Named("T2DataService")
private DataService T2DataService;
@Inject
@Named("T3DataService")
private DataService T3DataService;
//...
}
此外,没有什么可以阻止您使用注入的服务填充地图,以便于查找:
private Map<DataType, DataService> serviceMap;
@PostConstruct
public void createMap() {
serviceMap = new HashMap<>();
serviceMap.put(T1, T1DataService);
serviceMap.put(T2, T2DataService);
serviceMap.put(T3, T3DataService);
}
public void doStuff(final Request request) {
serviceMap.get(request.datatype).doStuff();
}