Spring注入不同的服务实现

时间:2017-03-26 17:04:03

标签: 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.");
        return new Report();
    }
}

这段代码的新业务要求是什么:

  • 实施将与新报告引擎通信的新ReportService_2,但新服务仍具有相同签名的generate()方法;
  • 实现在运行时基于某些预定义配置在这些服务之间切换的可能性;
  • 作为一种选择:考虑在最近的特征中引入新的ReportServices的能力。

好的,让我们开始实施上面提到的所有步骤:

第1步:

ReportService_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();
    }
}

@Qualifier("ReportService_1")

添加ReportService_1Impl
@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步:

如何根据配置在运行时间切换2个服务?

坦率地说,我不确定如何正确实施此任务,我刚刚介绍了ReportServiceReportService_1Impl扮演Container或Wrapper角色的新ReportService2_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's的能力。

我不知道如何正确实现这一点,因为对于当前的实现,每次我将添加新的ReportService_N我都需要记住,我肯定需要注入新创建的ReportService_N ReportServiceImpl,它看起来像:

@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;

相信,过去已经多次解决了这种问题,并且已经定义了一些我需要使用的模式。

有人可以给我建议或模式名称,帮助我解决上一个场景中的问题吗?

1 个答案:

答案 0 :(得分:1)

你使事情变得很复杂,你可以使用@Resource(name="${reportService}")轻松动态地分配一个bean,如下所示,即你实际上可以将bean名称(你想在运行时注入的那个)外化到{{1 }}

我已将application.properties用于Controller autowire,但在您喜欢的任何弹簧组件中也可以这样做。

ReportService

您需要在@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_1 bean名称等属性
  

当配置存储在DB中时,情况怎么样?或案例,   当我们需要根据某些人决定使用哪种服务时   传入参数?

如果您希望从数据库配置属性,那么您需要创建一个新的application.properties并告诉spring您使用它,这是一个给定here创建数据库属性的简单示例。

下一种情况是,如果您想使用某些变量基于某些@PropertySource - if条件动态传递对象,则需要动态传递else对象(使用多态性) )很好地解释here