spring接口多实现类,该依赖注入哪一个?(spring 多个实现类)

  本篇文章为你整理了spring接口多实现类,该依赖注入哪一个?(spring 多个实现类)的详细内容,包含有spring 接口和实现类注入 spring 多个实现类 spring常用接口和类 spring调用接口调用实现类 spring接口多实现类,该依赖注入哪一个?,希望能帮助你了解 spring接口多实现类,该依赖注入哪一个?。

  一、问题的描述

  在实际的系统应用开发中我经常会遇到这样的一类需求,相信大家在工作中也会经常遇到:

  同一个系统在多个省份部署。

  一个业务在北京是一种实现方式,是基于北京用户的需求。

  同样的业务在上海是另外一种实现方式,与北京的实现方式大同小异

  遇到这样的需求,我们通常会定义一个业务实现的接口,比如:

  

public interface IDemoService {

 

   public void doSomething();

  

 

  在北京环境下这样实现,比如:

  

@Component

 

  public class DemoServiceBeijing implements IDemoService {

   @Override

   public void doSomething() {System.out.println("北京的业务实现");}

  

 

  在上海环境下这样实现,比如:

  

@Component

 

  public class DemoServiceShanghai implements IDemoService {

   @Override

   public void doSomething() {System.out.println("上海的业务实现");}

  

 

  然后我们写一个模拟业务测试用例

  

@SpringBootTest

 

  class DemoApplicationTests {

   //这里注入的demoService是DemoServiceShanghai,还是DemoServiceBeijing?

   @Resource

   IDemoService demoService;

   @Test

   void testDemoService() {

   demoService.doSomething();

  

 

  当我们执行这个测试用例的时候一定会报错,因为Spring发现了两个IDemoService的实现类。它不知道去实例化哪一个实现类,来作为IDemoService的实际业务处理bean。当然我们期望的状态是:

  在北京部署系统的时候,使用DemoServiceBeijing作为IDemoService的实现类完成依赖注入

  在上海部署系统的时候,使用DemoServiceShanghai作为IDemoService的实现类完成依赖注入

  二、相对低级解决方案

  面对上面的需求,先说几个相对低级的解决方案,这几个方案虽然可以实现我们期望的状态,但是对运维不够友好。

  2.1. 方案一:使用@Primary注解

  假如在北京部署系统的时候,在DemoServiceBeijing的类上面加上@Primary,该注解的作用就是强迫从多个实现类里面选一个实现类,如果Spring不知道选哪一个,我们告诉它一个默认的。

  

@Primary

 

  @Component

  public class DemoServiceBeijing implements IDemoService {

  

 

  2.2. 方案二:使用@Resource注解

  因为Resource注解默认使用名称进行依赖注入,所以变量名明确叫做demoServiceBeijing(首字母小写),使用的就是DemoServiceBeijing实现类。

  

@Resource

 

  IDemoService demoServiceBeijing; //这里的变量名称指定了bean名称

  //IDemoService demoService; 被替换掉

  

 

  或者

  

@Resource(name = "demoServiceBeijing") //使用resource注解明确指定名称

 

  IDemoService demoService;

  

 

  2.3.方案三:使用@Qualifier注解

  与上文同样的道理,使用@Qualifier注解,指定bean的名称进行依赖注入

  

@Qualifier("demoServiceBeijing") //使用Qualifier注解明确指定名称

 

  @Resource

  IDemoService demoService;

  

 

  上面所提到的三个方案虽然都可以解决:在不同的部署环境下使用不同的接口实现类完成依赖注入的问题。但是这样不好,因为一旦我们要把部署环境从beijing(北京)换成shanghai(上海),就需要把上面的注解的位置或者内容全都修改一遍(所有的实现类代码都要修改)。

  三、相对高级的解决方案

  我们提出进一步的期望:就是只修改一个配置就能完成部署环境切换的操作。比如:

  

deploy:

 

   province: beijing

  

 

  当我们期望把部署环境从北京切换到上海的时候,只需要将上文配置中的beijing 改成 shanghai ,这该怎么实现呢?

  在北京的实现类上面加上ConditionalOnProperty注解,havingValue的值为beijing

  

@Component

 

  @ConditionalOnProperty(value="deploy.province",havingValue = "beijing")

  public class DemoServiceBeijing implements IDemoService {

  

 

  在上海的实现类上面加上ConditionalOnProperty注解,havingValue的值为shanghai

  

@Component

 

  @ConditionalOnProperty(value="deploy.province",havingValue = "shanghai")

  public class DemoServiceShanghai implements IDemoService {

  

 

  ConditionalOnProperty注解在这里的作用就是:读取配置文件发现deploy.province,并将该配置的值与havingValue匹配,匹配上哪一个就实例化哪一个类作为该接口的实现类bean注入到Spring容器中(当然注入过程需要配合@Component注解实现)。

  欢迎关注我的公告号:字母哥杂谈,回复003赠送作者专栏《docker修炼之道》的PDF版本,30余篇精品docker文章。字母哥博客:zimug.com

  以上就是spring接口多实现类,该依赖注入哪一个?(spring 多个实现类)的详细内容,想要了解更多 spring接口多实现类,该依赖注入哪一个?的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: