当两个实现类实现了同一个接口,并且这两个实现类都被spring IoC容器所管理。那么在我们使用@Autowired注解该bean时候,spring如何知道开发者是要注入哪个bean呢?
Spring中提供了两种办法(我所知道的两种)来解决这个问题。
首先是@Primary注解,当优先使用哪个bean时,在该实现类上加上此注解。那么Spring在注入bean时候就优先注入该bean。
Fruit接口
public interface Fruit {
String sayFruitName();
}
Apple实现Fruit接口,并且加上@Primary注解
@Component
@Primary
public class Apple implements Fruit{
@Override
public String sayFruitName() {
System.out.println("Apple!");
return "Apple!";
}
}
Banana 实现Fruit接口
@Component
public class Banana implements Fruit{
@Override
public String sayFruitName() {
System.out.println("Banana!");
return "Banana!";
}
}
为了更加贴近生产环境,笔者使用了Springboot中的Controller的来测试。
@Controller
public class TestPrimaryAndQualifier {
@Autowired
Fruit fruit;
@RequestMapping("/getFruit")
@ResponseBody
public String getFruit (){
return fruit.sayFruitName();
}
}
当访问http://localhost:8080/getFruit时候返回的是"Apple!"
这时候有个问题,就是我们怎么去用另一个bean呢?这里其实@Primary这个注解在生产环境不实用。
@Qualifier才是我们所需要的。来看看@Qualifier 是如何work的。
@Qualifier是根据我们向spring IoC容器中注入bean时候的名称来选择我们所需要的bean。
在向IoC容器注入bean时候,bean的默认名称是类名的首字母小写。Apple在容器汇中的bean名称为apple,Banana同理。当然我们也可以在注入的时候指定名称,show my code.
向容器中注入bean,其名称为bigBanana。
@Component("bigBanana")
public class Banana implements Fruit{
@Override
public String sayFruitName() {
System.out.println("Banana!");
return "Banana!";
}
}
@Qualifier(“bigBanana”)指定了我们要的bean为Banana的实例。
@Controller
public class TestPrimaryAndQualifier {
@Autowired
@Qualifier("bigBanana")
Fruit fruit;
@RequestMapping("/getFruit")
@ResponseBody
public String getFruit (){
return fruit.sayFruitName();
}
}
当访问http://localhost:8080/getFruit时候返回的是"Banana!"
总结:
@Primary:在众多相同的bean中,优先选择用@Primary注解的bean(该注解加在各个bean上),但是不具有灵活性
@Qualifier:在众多相同的bean中,@Qualifier指定需要注入的bean(该注解跟随在@Autowired后),灵活性强。
不求打赏,点赞关注走一波