2021-11-27_把白天工作中不会的@Primary注解弄明白

学习自 https://www.cnblogs.com/jyy599/p/12410571.html 。

1. 备注

1.1 本文不写工作具体内容(因为这是商业机密),只写下班后我怎么把具体技术细节弄明白的。

1.2 同时要感谢同事不仅帮我解决了问题还帮我讲了问题所在,从而让我下班后的学习有了方向。

1.3 具体的学习过程是:根据 https://www.cnblogs.com/jyy599/p/12410571.html 这篇帖子,结合同事指导,理解思想并敲代码进行验证。

2. 为什么要有@Primary这个注解

2.1 正常情况

接口:

public interface Singer {
    String sing(String lyrics);
}

实现类:

/**
 * 加注解@Service(org.springframework.stereotype.Service),让Spring识别
 *
 * @author konglc
 * @date 2021/11/27 23:52
 */
@Service
public class MetalSinger implements Singer {

    @Override
    public String sing(String lyrics) {
        System.out.println("I am singing with DIO voice: " + lyrics);
        return "I am singing with DIO voice: " + lyrics;
    }
}
public class OperaSinger implements Singer {

    @Override
    public String sing(String lyrics) {
        System.out.println("I am singing in Bocelli voice: " + lyrics);
        return "I am singing in Bocelli voice: " + lyrics;
    }
}

注入:

@Service
public class SingerService {
    private static final Logger logger = LoggerFactory.getLogger(SingerService.class);

    @Autowired
    private Singer singer;

    public String sing() {
        return singer.sing("song lyrics");
    }
}

OperaSinger没加注解,所以没有被Spring识别。我改写了springboot+vue项目的表格save方法,进行测试。

@Autowired
    private SingerService singerService;

@PostMapping
    public Result<?> save(@RequestBody User user){
//        if (user.getPassword() == null) {
//            user.setPassword("123456");
//        }
//        userService.save(user);
        singerService.sing();

        return Result.success();
    }

结果是控制台打印如下,即注入了metalSinger(执行了metalSinger的sing方法):

I am singing with DIO voice: song lyrics

2.2 异常情况

当OperaSinger加了注解,也被Spring识别时,

@Service
public class OperaSinger implements Singer {

    @Override
    public String sing(String lyrics) {
        System.out.println("I am singing in Bocelli voice: " + lyrics);
        return "I am singing in Bocelli voice: " + lyrics;
    }
}

项目编译时就会报错:

Field singer in com.example.demo.service.impl.SingerService required a single bean, but 2 were found:
    - metalSinger: defined in file [MetalSinger.class]
    - operaSinger: defined in file [OperaSinger.class]

3. 使用@Primary注解:

@Primary
@Service
public class OperaSinger implements Singer {

    @Override
    public String sing(String lyrics) {
        System.out.println("I am singing in Bocelli voice: " + lyrics);
        return "I am singing in Bocelli voice: " + lyrics;
    }
}

结果是控制台打印结果如下,即注入了operaSinger(执行了operaSinger的sing方法):

I am singing in Bocelli voice: song lyrics

4. 总结:当接口有多个实现类时,如果Spring根据类型无法选择到底注入哪一个,这时,可以用@Primary注解来告诉Spring在犹豫的时候优先选择哪一个具体的实现。

上一篇:数据库实验ch2-索引实验


下一篇:SQL初学者实用基础三