Java Spring注入不同的服务实现
这就是我们目前的情况:Java Spring注入不同的服务实现,java,design-patterns,Java,Design Patterns,这就是我们目前的情况: interface ReportService { Report generate(); } 和接口实现: @Service public class ReportService_1Impl implements ReportService { public Report generate() { System.out.println("Report Service 1: generate Report.");
interface ReportService {
Report generate();
}
和接口实现:
@Service
public class ReportService_1Impl implements ReportService {
public Report generate() {
System.out.println("Report Service 1: generate Report.");
return new Report();
}
}
这段代码的新业务需求是什么:
- 实现新的
,它将与新的报表引擎通信,但新的服务仍然具有相同的ReportService_2
方法和相同的签名李>generate()
- 基于一些预定义的配置,实现在运行时在这些服务之间切换的可能性李>
- 作为一种选择:考虑在最近的功能中引入新的
的能力ReportServices
报告服务\u 2
:
@Service
@Qualifier("ReportService_2")
public class ReportService_2Impl implements ReportService {
public Report generate() {
System.out.println("Report Service 2: generate Report.");
return new Report();
}
}
为ReportService\u 1Impl添加@限定符(“ReportService\u 1”)
@Service
@Qualifier("ReportService_1")
public class ReportService_1Impl implements ReportService {
public Report generate() {
System.out.println("Report Service 1: generate Report.");
return new Report();
}
}
步骤2:
如何在运行时根据配置在两个服务之间切换
坦率地说,我不知道如何正确地实现这项任务,我刚刚介绍了新的ReportService
,它扮演了ReportService\u 1Impl
和ReportService2\u Impl
的容器或包装器的角色,并确定了需要使用哪些实现:
@Service
public class ReportServiceImpl implements ReportService {
@Autowired
@Qualifier("ReportService_1")
private ReportService reportService_1;
@Autowired
@Qualifier("ReportService_2")
private ReportService reportService_2;
private ReportService getActiveReportService() {
return true ? reportService_1 : reportService_2;
}
public Report generate() {
return getActiveReportService().generate();
}
}
看起来很难看,但我相信我们可以忍受
最后一步,我需要实现以下要求:
考虑在最近的功能中引入新的ReportService的功能。
我不知道如何正确地实现这一点,因为在当前的实现中,每次添加新的ReportService\N
时,我都需要记住,我肯定需要在reportserviceinpl
中注入新创建的ReportService\N
,它看起来像:
@Service
public class ReportServiceImpl implements ReportService {
@Autowired
@Qualifier("ReportService_1")
private ReportService reportService_1;
@Autowired
@Qualifier("ReportService_2")
private ReportService reportService_2;
@Autowired
@Qualifier("ReportService_3")
private ReportService reportService_3;
@Autowired
@Qualifier("ReportService_4")
private ReportService reportService_4;
@Autowired
@Qualifier("ReportService_N")
private ReportService reportService_N;
我相信,这种问题在过去已经解决过多次,并且已经定义了一些我需要使用的模式
有人能给我一些建议或模式名来帮助我解决上一个场景中的问题吗?您让事情变得非常复杂,相反,您可以通过使用@Resource(name=“${reportService}”)
轻松地动态分配bean,如下所示,也就是说,您实际上可以将bean名外部化(无论您想在运行时注入哪个)到application.properties
我已经使用了Controller
来autowire
您的ReportService
,但是可以在您喜欢的任何spring组件中执行相同的操作
@Controller
public class YourContrller {
@Autowired
@Resource(name="${reportService}")
private ReportService reportService;
public Report generate() {
return reportService.generate();
}
}
@Service("ReportService_1")//name this service as ReportService_1
public class ReportService_1Impl implements ReportService {
//actual code
}
@Service("ReportService_2")//name this service as ReportService_2
public class ReportService_2Impl implements ReportService {
//actual code
}
您需要在应用程序中配置一个类似reportService=reportService\u 1的属性
当配置存储在DB?或case中时,
当我们需要根据某些信息决定使用哪种服务时
传入参数
如果希望从数据库中配置属性,则需要创建一个新的@PropertySource
,并告诉spring您正在使用它,下面给出了一个创建数据库PropertySource的简单示例
下一种情况是,如果您希望使用一些变量根据一些if
-else
条件动态传递对象,则需要动态传递ReportService
对象(使用多态性)正如很好地解释的那样。选择策略设计模式很好的方法!非常喜欢!但是,当配置存储在DB?或case中时,当我们需要根据一些传入参数决定使用哪种服务时,情况如何?请提供建议。更新了我的答案,您可以查看一下