@ Autowired
它注入的机制最基本的一条是根据类型( by type ), 我们回顾IoC 容器的顶级接口BeanFactory ,就可以知道IoC 容器
是通过getBean 方法获取对应Bean 的,而getBean 又支持根据类型( by type )或者根据名称( by name )。
如果Dog为Animal的实现类,则通过以下注解可以注入
@Autowired private Animal animal = null;
但如果同时有Dog,Cat两个实现类,则以上的注入会报错。
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'businessman': Unsatisfied dependency expressed through field 'animal'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.springboot.chapter3.Animal' available: expected single matching bean but found 2: cat,dog......
Spring IoC 容器并不能知道你需要注入什么动物(是狗? 是猫? )
修改为:
@Autowired private Animal dog = null;
我们只是将属性的名称从animal 修改为了dog,那么我们再测试的时候,你可以看到是
采用狗来提供服务的。那是因为@Autowired 提供这样的规则, 首先它会根据类型找到对应的Bean,
如果对应类型的Bean 不是唯一的,那么它会根据其属性名称和Bean 的名称进行匹配。如果匹配得
上,就会使用该Bean :如果还无法匹配,就会抛出异常。
这里还要注意的是@Autowired 是一个默认必须找到对应Bean 的注解,如果不能确定其标注属
性一定会存在并且允许这个被标注的属性为null , 那么你可以配置@Autowired 属性required 为false
@Autowired(required = false)
显然以上的改法是一种憋屈的做法,好好的动物固定成了狗。注解@Primary ,它是一个修改优先权的注解,当我们有猫有狗的时候,假设这次需要使用猫, 那么只需要在猫类的定义上加入@Primarγ 就可以了,
@Component @Primary public class Cat implements Animal { ... }
这里的@Primary 的含义告诉S pring IoC 容器, 当发现有多个同样类型的Bean 时\ 请优先使用
我进行注入,于是再进行测试时会发现,系统将用猫为你提供服务。因为当Spring 进行注入的时候
虽然它发现存在多个动物, 但因为C at 被标注为了@Primarγ ,所以优先采用Cat 的实例进行了注入,
这样就通过优先级的变换使得IoC 容器知道注入哪个具体的实例来满足依赖注入。
然后,有时候@Primary 也可以使用在多个类上,也许无论是~-~i还是狗都可能带上@Primary 注解, 其结果是IoC 容器还是无法区分采用哪个Bean 的实例进行注入, 又或者说我们需要更加灵活的机制来实现注入,那么@ Q ue li fier 可以满足你的这个愿望。它的配置项va lue 需要一个字符串去定义,它将与@ A ut ow ired 组合在一起,通过类型和名称一起找到Bean 。我们知道Bean 名称在Spring IoC容器中是唯一的标识,通过这个就可以消除歧义性了
@Autowired @Qualifier("cat") private Animal animal = null;
在上面,我们都基于一个默认的情况,那就是不带参数的构造方法下实现依赖注入。但事实上,
有些类只有带有参数的构造方法,于是上述的方法都不能再使用了。为了满足这个功能,我们可以
使用@Autow ired 注解对构造方法的参数进行注入
@Component public class Businessman implements Person { @Autowired(required = false) private Animal dog = null; // @Autowired // @Qualifier("cat") private Animal animal = null; public Businessman(@Autowired @Qualifier("dog") Animal animal){ this.animal = animal; } @Override public void service() { this.animal.use(); } @Override public void setAnimal(Animal animal) { this.animal = animal; } }