学习自 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在犹豫的时候优先选择哪一个具体的实现。