### 发生的场景
类结构图 :
![](image/ClassRelation.png)
当一个方法接收接口作为参数,而其中,这个接口有多个实现,自动注入报错
```java
@Autowired
public void comeRoom(Human human){
this.human = human;
}
```
```java
@Component
public class Eisteddfod implements Human { ... }
@Component
public class Knight implements Human { ... }
@Component
public class Merchant implements Human { ... }
```
**报错信息 :**
![](image/error1.png)
### 第一种解决方式 : 设置首选bean
#### Java方式实现
```java
@Component
@Primary
public class Knight implements Human {...}
```
#### XML方式实现
```xml
<bean id="knight"
class="autoAmbiguity.bean.Knight"
primary="true" />
```
**缺点 : 在有两个首选的Dessert bean的时候,这就会带来了新的歧义性问题**
### 第二种解决方式 : 设置限定符
```java
@Autowired
@Qualifier("knight")
public void comeRoom(Human human){
this.human = human;
}
```
@Qualifier注解所设置的参数限定符
你重构了IceCream类,将其重命名为Gelato的话,这就无法匹配comeRoom()方法中的限定符
**缺点 : 方法上所指定的限定符与要注入的bean的名称是紧耦合的。对类名称的任意改动都会导致限定符失效**
所有的bean都会给定一个默认的限定符,这个限定符与bean的ID相同
**解决方案 : 为bean设置自己的限定符,而不是依赖于将bean ID作为限定符**
```java
@Component
@Qualifier("knight")
public class Knight implements Human {...}
```
#### 使用自定义的限定符注解
> Java不允许在同一个条目上重复出现相同类型的多个注解
>
> [1]Java 8允许出现重复的注解,只要这个注解本身在定义的时候带有@Repeatable注解就可以。不过,Spring的@Qualifier注解并没有在定义时添加@Repeatable注解。
```java
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Brave {
}
```
```java
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Mercy {
// 仁慈
}
```
#### 设置类的多个限定符
```java
@Component
@Brave
@Mercy
public class Knight implements Human { ... }
```
通过声明自定义的限定符注解,我们可以同时使用多个限定符,不会再有Java编译器的限制或错误
```java
@Autowired
@Brave
@Mercy
public void comeRoom(Human human) {
this.human = human;
}
```
网友评论