您的位置:首页 > 编程语言 > Java开发

处理自动装配的歧义性

2017-10-13 22:18 453 查看

处理自动装配的歧义性

自动装配能够提供很大的帮助,因为它会减少装配应用程序组件时所需要的显式配置的数量。当不仅有一个bean能够匹配结果的话,这种歧义性会阻碍Spring自动装配属性、构造器参数或方法参数。

例如我们使用
@Autowired
注解标注了setWord()方法:

@Autowired
public void setWord(Word word) {
this.word = word;
}


其中Word是一个接口,有三个类实现了这个接口

@Component
public class A implements Word {
// ...
}

@Component
public class B implements Word {
// ...
}

@Component
public class C implements Word {
// ...
}


如果我们不做任何处理,让Spring直接进行扫描的话,Spring将无法做出选择,将会抛出
NoUniqueBeanDefinitionException


为了解决这种冲突,Spring提供了如下方法。

标示首选的bean

使用@Primary注解: 使用此注解标示的bean将优先被Spring应用创建。方式有以下三种:

// @Primary与@Component组合用在组件扫描的bean上
@Component
@Primary
public class A implements Word {
// ...
}


// 与JavaConfig和结合使用
@Bean
@Primary
public Word a() {
return new A();
}


<!-- xml配置Primary -->
<bean id="a" class"com.zheng.spring.A" primary="true" />


限定自动装配的bean

@Qualifier注解是使用限定符的主要方式。它可以与@Autowired@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean。

例如要将A注入到setWord()里面

@Autowired
@Qualifier("a") // 字面量一般为@Bean注解标示类名的第一个字母小写形式
public void setWord(Word word) {
this.word = word;
}


但当我们改变A类的名字,Spring将会出现注入失败,这时我们就可以设置自己的限定符,我们需要在bean声明上添加@Qualifier注解。如下所示

@Component
@Qualifier("zheng")
public class A implements Word {
// ...
}


注入时只需这样写就不怕任意改动类名

@Autowired
@Qualifier("zheng")
public void setWord(Word word) {
this.word = word;
}


@Qualifier也可以与@Bean注解一起使用:

@Bean
@Qualifier("zheng")
public Word a() {
return new A();
}


使用自定义的限定符注解

但有时我们会出现一个Bean具有相同特性,例如下面的B

@Component
@Qualifier("zheng")
public class B implements Word {
// ...
}


这样子Spring又没法识别了,我们想到了可以再细化两者的特性,如下

@Component
@Qualifier("zheng")
@Qualifier("length")
public class A implements Word {
// ...
}


但是Java不允许在一个条目重复出现相同的注解,所以这种方式是不可行的,但我们可以创建自定义的限定符注解,借助这样的注解来表达bean所希望限定的特性。这里

所需要做的就是创建一个注解,它本身要使用@Qualifier注解来标注。

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Zheng {}


所以上面的bean可以这样配置

@Component
@Zheng
@Length
public class A implements Word {
// ...
}


为了得到A bean,setWord()方法可以这样使用注解:

@Autowired
@Zheng
@Length
public void setWord(Word word) {
this.word = word;
}


通过声明自定义的限定符注解,我们可以同时使用多个限定符,不会再有Java编译器的限制或错误。与此同时,相对于使用原始的@Qualifier并借助String类型来指定限定符,自定义的注解也更为类型安全。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring bean