SpringBoot中一个接口多个实现类,如何自由选择,这是一把《屠龙宝刀》

一个接口难免会有多个实现类,不同的实现类有各自的需求,如何在项目中实现根据不同项目,自由切换实现类呢?

废话不多说,直接上代码,文末有源码,直接测试

1.接口代码

package com.cj.interfaces;

public interface ITestService {
     
    void test();
}

2.实现类1,使用@Service,且其中指定bean的名字为“s1”

package com.cj.interfaces;
import org.springframework.stereotype.Service;

@Service("s1")
public class TestServiceImpl1 implements ITestService {
     
    @Override
    public void test() {
     
        System.out.println("接口1实现类 ...");
    }
}

3.实现类2,使用@Service,啥都不指定,使用默认

package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl2 implements ITestService {
     
    @Override
    public void test() {
     
        System.out.println("接口2实现类 ...");
    }
}

4.实现类3,依旧使用@Service,同时指定bean的注入名称为“s3”

package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service("s3")
public class TestServiceImpl3 implements ITestService {
     
    @Override
    public void test() {
     
        System.out.println("接口3实现类 ...");
    }
}

上面就构造了一个接口,三个实现类
ok了吗?

5.测试代码

package com.cj.interfaces;

import org.junit.Test;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

import static org.junit.jupiter.api.Assertions.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ITestServiceTest {
     

    //有指定bean注入名字的,使用bean的名字
    //qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,
    // 需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!
    @Autowired
    @Qualifier(value = "s1")
    ITestService testService;    //正常启动

    //没有指定bean注入名字的,使用该类首字符小写的bean的名字
    //使用默认的
    @Resource(name = "testServiceImpl2")
    ITestService testService2;    //正常启动

    //通过@Resource注入,根据@Service指定的名称区分
    @Resource(name = "s3")
    ITestService testService3;    //正常启动

    @Test
   public void test1() {
     
        testService.test();

        testService2.test();

        testService3.test();     
    }
}

运行结果

SpringBoot中一个接口多个实现类,如何自由选择,这是一把《屠龙宝刀》_第1张图片
分析:

  1. 方法一:使用@Autowired @Qualifier(value = “s1”)
  2. 方法二:使用@Resource(name = “testServiceImpl2”),没有指定bean注入名字的,使用该类首字符小写的bean的名字
  3. 方法三:使用@Resource(name = “s3”),通过@Resource注入,根据@Service指定的名称区分

6.使用@Primary注解

上接口

package com.cj.interfaces;

public interface IPrimaryService {
     
    void test();
}

实现类1,有注解@Primary

package com.cj.interfaces;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

@Service
@Primary
public class TestPrimaryImpl1 implements IPrimaryService{
     
    @Override
    public void test() {
     
        System.out.println("Primary 1");
    }
}

实现类2

package com.cj.interfaces;

import org.springframework.stereotype.Service;

@Service
public class TestPrimaryImpl2  implements IPrimaryService{
     
    @Override
    public void test() {
     
        System.out.println("Primary 2");
    }
}

测试类

     @Autowired
    IPrimaryService primaryService;

    @Test
   public void test1() {
     
        primaryService.test();
    }

测试结果
在这里插入图片描述
分析:

  1. 类TestPrimaryImpl1 上面添加了@Primary
  2. 类TestPrimaryImpl2 不添加
  3. 注入容器的时候,@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现

有了多个实现类,那如何通过配置来动态选择实现类?

为了和面区分,我们再来一个接口,分开讨论

package com.cj.interfaces;

public interface ITestServiceConditional {
     
    void test();
}

实现类1

package com.cj.interfaces;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

/**
 * 使用配置文件控制注入:
 * 我们需要在实现类上添加配置文件注解,使用配置文件控制该实现类是否生效
 */
@Service
@Configuration
@ConditionalOnProperty(prefix = "demo.test.service",name = "impl",havingValue = "one")
public class TestServiceImpl4 implements ITestServiceConditional {
     
    @Override
    public void test() {
     
        System.out.println("接口4实现类 ...");
    }
}

实现类2

package com.cj.interfaces;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

@Service
@Configuration
@ConditionalOnProperty(prefix = "demo.test.service",name = "impl",havingValue = "two")
public class TestServiceImpl5 implements ITestServiceConditional {
     
    @Override
    public void test() {
     
        System.out.println("接口5实现类 ...");
    }
}

配置文件

demo:
  test:
    service:
      impl: one

测试类


    @Autowired
    ITestServiceConditional testServiceConditional;

    @Test
   public void test1() {
     
        testServiceConditional.test();
    }

执行结果

在这里插入图片描述

测试源码

你可能感兴趣的:(spring,工具,1024程序员节,多个实现类,接口多个实现类,一个接口多个实现类,动态实现类)