Bean之间的依赖,在SpringIOC容器中,我们称为依赖注入。
列如:人类有时候会利用一些动物去完成一些事情,比如狗是看门,猫抓老鼠。于是做一些事情就依赖于那些可爱的动物。
为了更好展现此过程,我们做一个演示
第一步:定义人和动物接口,并写分别写两个实现类
接口:Person
package com.atstudying.demo.POJO;
public interface Person {
//使用动物服务
public void service();
//设置动物
public void setAnimal(Animal animal);
}
接口:Animal
package com.atstudying.demo.POJO;
public interface Animal {
public void use();
}
实现类:BussinessPerson.class
package com.atstudying.demo.POJO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BussinessPerson implements Person{
@Autowired
private Animal animal=null;
public BussinessPerson() {
super();
}
@Override
public void service(){
this.animal.use();
}
@Override
public void setAnimal(Animal animal){
this.animal=animal;
}
}
实现类:Dog.class
package com.atstudying.demo.POJO;
import org.springframework.stereotype.Component;
@Component
public class Dog implements Animal {
@Override
public void use(){
System.out.print("狗"+"["+Dog.class.getSimpleName()+"]"+"看门");
}
}
第二步:测试
DemoApplication.class
package com.atstudying.demo.Demo;
import com.atstudying.demo.POJO.BussinessPerson;
import com.atstudying.demo.POJO.Person;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext();
Person person=applicationContext.getBean(BussinessPerson.class);
person.service();
}
}
package com.atstudying.demo.POJO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BussinessPerson implements Person{
@Autowired
private Animal animal=null;
public BussinessPerson(@Autowired @Qualifier("dog") Animal animal) {
super();
this.animal=animal;
}
@Override
public void service(){
this.animal.use();
}
@Override
public void setAnimal(Animal animal){
this.animal=animal;
}
}
package com.atstudying.demo.POJO;
import org.springframework.stereotype.Component;
@Component
public class Dog implements Animal {
@Override
public void use(){
System.out.print("猫"+"["+Dog.class.getSimpleName()+"]"+"吃老鼠");
}
}
那么因为这个类只是定义了一个动物属性(Animal),而我们却有两个动物,猫和狗类,那么SpringIOC容器会如何注入呢 ?如果再继续进行测试会抛出如下异常。
Caused by: org . springfr amework. beans. factory . NoUni queBeanDe finitionException: No
qualifying bean of type ' com. springboot . chapter3.pojo. definition.Animal' available:expected
**single matching bean but found 2: cat, dog**
at org. springframework. beans. factory.config. DependencyDescriptor. resolveNotUnique(DependencyDescriptor. java:173)
at org. springframework. beans . factory.support. DefaultListableBeanFactory .doResolveDependency (DefaultListableBeanFactory.java:1116)
at org. springframework . beans. factory.support.DefaultListableBeanFactory.resolveDependency (Defaul tListableBeanFactory.java:1066)
at org. springframework . beans . factory. annotation .AutowiredAnnotationBeprocessorSAutowiredFieldE lement . inject (Autowiredannotatineaostrocessor java:585)anPost
onBe14 more
@Autowired
private Animal animal=null;
修改为
@Autowired
private Animal Dog=null;
@Autowired(required = false)
同样,它除了可以标注属性外,还可以标注方法,如seAnimal方法,如下所示:
@Override
@Autowired
public void setAnimal (Animal animal){
this.animal = animal;
}
我们可以使用该方法从IOC容器中找到对应的动物进行注入,我们还可以使用在方法参数上,后面博客会在谈到
@Component
@Primary
public class Cat implements Animal ()
......
解决办法:@Qualifier 可以满足你的这个愿望。它的配置项value需要一个字符串去定义,它将与 @Autowired 组合在一起,通过类型和名称一起找到 Bean.我们知道Bean名称在Spring loc容器中是唯一的标识,通过这个就可以消除歧义性了。
下面假设猫已经标注 @Primary 而我们因此需要修改BussinessPerson属性animal的标注以适合我们的需要,如下所示:
@Autowired
@Qualifier ("dog")
private Animal animal
一旦这样声明,SpringIoC将会以类型和名称去寻找对应的Bean.显然也只能找到狗为我们服务了。