前言

在SpringBoot项目中,如果一个Service层接口,有多种实现方式,我们应该如何去选择正确的实现类去注入呢?
废话不多说,看例子,上代码:

// TestService.java 定义接口
public interface TestService {
    void testMethod();
}

// TestServiceImpl1.java 实现类一
@Service
public class TestServiceImpl1 implements TestService {
    protected static final Logger logger = LoggerFactory.getLogger(TencentCosUtils.class);
    @Override
    public void testMethod() {
        logger.info("TestServiceImpl1");
    }
}

// TestServiceImpl2.java 实现类二
@Service
public class TestServiceImpl2 implements TestService {
    protected static final Logger logger = LoggerFactory.getLogger(TencentCosUtils.class);
    @Override
    public void testMethod() {
        logger.info("TestServiceImpl2");
    }
}

当我们遇到这种情况时,SpringBoot项目扫描到了多个实现类,如果直接注入,会直接报异常:
image.png
那我们该如何去选择相应的实现类呢?

使用@Qualifier注解选择实现类

我们在调用时,通过使用@Qualifier来指定实现类,来实现对指定类的依赖注入:

@Autowired
@Qualifier("testServiceImpl1")
TestService testService;

@GetMapping("test")
public R test(){
     testService.testMethod();
     return R.ok();
}

访问控制器,发现在控制台中成功的输出了testServiceImpl1。
image.png

使用@Primary注解在指定默认实现类

在SpringBoot项目中,我们还可以通过在实现类中添加@Primary注解来使其变成一个主要实现类,这样在SpringBoot扫描到多个实现类时,会自动选择主要实现类进行注入。

// TestServiceImpl2.java
@Service
@Primary
public class TestServiceImpl2 implements TestService {
    protected static final Logger logger = LoggerFactory.getLogger(TencentCosUtils.class);
    @Override
    public void testMethod() {
        logger.info("TestServiceImpl2");
    }
}
@Autowired
TestService testService;

@GetMapping("test")
public R test(){
    testService.testMethod();
    return R.ok();
}

访问控制器,发现在控制台中成功的输出了testServiceImpl2。
image

@Qualifier VS @Primary

既然两种方式都可以实现在多个实现类中自动注入,那他们的区别是什么呢?

  • @Qualifier是指定实现类,在每次注入是都要指定我们需要注入的实现类。
  • @Primary是设置首选实现类,在注入时发现了多个实现类,定义了首选项。
  • @Qualifier的优先级高于@Primary,如果定义了指定实现类,那么即使定义了首选实现类,也会自动注入到指定实现类中。

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议