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
    的能力
好的,让我们开始实施上面提到的所有步骤:

步骤1:

新的
报告服务\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中时,当我们需要根据一些传入参数决定使用哪种服务时,情况如何?请提供建议。更新了我的答案,您可以查看一下