我目前正在编写TDEE计算器,该计算器的“每日总能源消耗”。换句话说,您一天燃烧的卡路里大约是多少。
有三个不同的公式。我想让最终用户选择他们要选择计算的公式。
现在我正在关注Spring Structure
在创建程序包和它们各自的类时,我意识到服务类将具有相同的方法getTdee()
,但是实现方式却不同。最好是,我想使用具有三种不同实现的接口,但是我知道您不能自动装配多个bean。有什么解决办法吗?还是我注定要重复三个程序包,每个程序包包含一个控制器,服务,请求有效负载?
控制器:
@RestController
@RequestMapping("/tdee")
public class Tdee{
private TdeeService tdeeService
@Inject
public Tdee(TdeeService tdeeService){
this.tdeeService = tdeeService;
}
@PostMapping
public getTdee(){
return tdeeService.getTdee();
}
}
服务:
@Named
public class TdeeService{
public int getTdee(){
//logic here
}
}
最好将TdeeService切换到一个接口,并实现所有三个公式:
@Named
KatchTdeeServiceImpl implements TdeeService{
@Override
public int getTdee(){
//logic here
}
}
@Named
HarrisTdeeServiceImpl implements TdeeService{
@Override
public int getTdee(){
//logic here
}
}
@Named
MiffinTdeeServiceImpl implements TdeeService{
@Override
public int getTdee(){
//logic here
}
}
总结我的问题:
理想情况下,我想创建一个具有一个服务接口,三个服务实现,一个控制器和一个有效载荷类的包,而不是创建三个具有控制器,服务和有效载荷的包。谢谢!
答案 0 :(得分:1)
那么您将根据用户传递的某些参数来确定要使用哪些实现?
实际上,如果有多个实现相同接口的bean,也可以注入它们。一种方法是使用@Qualifier
指定要注入的bean(按bean名称):
@RestController
@RequestMapping("/tdee")
public class Tdee{
@Autowired
@Qualifier("katchTdeeServiceImpl")
private TdeeService katchTdeeServce;
@Autowired
@Qualifier("harrisTdeeServiceImpl")
private TdeeService harrisTdeeService;
@PostMapping
public getTdee(FooRequest request){
if(request.isKatch()){
katchTdeeServce.getTdee();
}else if(requst.isHarris()){
harrisTdeeService.getTdee();
}
}
}
注意:
@Autowired
进行注入。 @Inject
似乎不起作用
与@Qualifier
@Qualifier
是spring软件包中的一个,而不是javax.inject
@Named("foo")
来定义其他名称。答案 1 :(得分:1)
除了使用@Qualifier
来唯一标识正确的实现所说的以外,您还可以自动装配一系列bean,例如:
@Autowired
private List<TdeeService> tdeeServices;
这使您可以提供一种更动态的方法。例如,假设您使用以下方法扩展TdeeService
界面:
boolean isSupported(String calculationType);
您可以这样实现:
@Override
public boolean isSupported(String calculationType) {
return "Harris".equals(calculationType);
}
最后,我假设您会在某个地方有一个@RequestParam
,用于标识您要使用哪种计算类型。如果是这种情况,您可以遍历tdeeServices
,调用isSupported()
方法以找到正确的实现,然后使用该方法实际进行计算。
例如:
@GetMapping
public int getTdee(@RequestParam String calculationType) {
return tdeeServices
.stream()
// Filter out the TdeeService that are not supported
.filter(service -> service.isSupported(calculationType))
// Obtain the amount of calories
.map(TdeeService::getTdee)
// Get any of the results
// Ideally, you'll only have one implementation that returns true for a specific calculationType
// If multiple implementation returned 'true', any will be picked
.findAny()
// If the calculationType is not supported, an exception will be thrown
.orElseThrow(UnsupportedCalculationTypeException::new);
}