高级装配 —— 如何处理自动装配的歧义性?
2017-07-28 15:21
375 查看
Q:自动装配时,什么情况下会产生歧义性?歧义性会导致什么?怎么处理?
A:如果不仅有一个 bean 能够匹配结果的话,就会出现歧义性。
它会阻碍 Spring 自动装配属性、构造器参数或方法参数,并抛出 NoUniqueBeanDefinitionException 异常。实际中,歧义性还是比较罕见的。
当出现歧义性的时候,Spring 提供了多种可选方案来解决:你可以将可选的 bean 中的某一个设为首选(primary)的 bean ; 或者使用限定符(qualifier)来帮助 Spring 将可选的 bean 的范围缩小到只有一个 bean。
出现歧义性的代码:
注意:如果你标示了两个或更多的首选 bean,那么它就无法正常工作了。
就解决歧义性问题而言,限定符更为强大。
设置首选bean的局限性:无法将可选方案的范围限定到唯一一个无歧义性的选项中。他只能标识一个优先的可选方案,当首选 bean 的数量超过一个时,无法进一步缩小可选范围。
A:@Qualifier 注解是使用限定符的主要方式。它可以与 @Autowired 和 @Inject 协同使用,在注入的时候指定想要注入进去的是哪个 bean。代码如下:
此时,方法上所指定的限定符与要注入的 bean 的名称是紧耦合的。
Q:如何创建自定义的限定符?
我们可以为 bean 设置自己的限定符,而不是依赖于将 bean ID 作为限定符。
A:在 bean 声明上添加 @Qualifier 注解。
为了能够使用多个限定符,我们需要自定义限定符注解。
Q:如何使用自定义的限定符注解?
A:
上一篇:高级装配 —— 条件化的 bean
下一篇:高级装配 —— 如何在不同的作用域中声明 bean?
A:如果不仅有一个 bean 能够匹配结果的话,就会出现歧义性。
它会阻碍 Spring 自动装配属性、构造器参数或方法参数,并抛出 NoUniqueBeanDefinitionException 异常。实际中,歧义性还是比较罕见的。
当出现歧义性的时候,Spring 提供了多种可选方案来解决:你可以将可选的 bean 中的某一个设为首选(primary)的 bean ; 或者使用限定符(qualifier)来帮助 Spring 将可选的 bean 的范围缩小到只有一个 bean。
出现歧义性的代码:
// 自动装配 Dessert 参数时,并没有唯一、无歧义的可选值。 @Autowired public void setDessert(Dessert dessert){ this.dessert = dessert; }
@Component public class Cake implements Dessert { } @Component public class Cookies implements Dessert { } @Component public class IceCream implements Dessert { }
Q:如何标示首选的 bean?
A:如下代码所示:/** * ①、@Primary 能够与 @Component 组合用在组件扫描的 bean 上。 */ @ 4000 Component @Primary public class IceCream implements Dessert { } /** * ②、也可以与 @Bean 组合用在 Java 配置的 bean 声明中。 */ @Bean @Primary public Dessert iceCream(){ return new iceCream(); } <!-- ③、XML 配置中,实现同样的功能 --> <bean id="iceCream" class="com.desserteater.IceCream" primary="true"/>
注意:如果你标示了两个或更多的首选 bean,那么它就无法正常工作了。
就解决歧义性问题而言,限定符更为强大。
设置首选bean的局限性:无法将可选方案的范围限定到唯一一个无歧义性的选项中。他只能标识一个优先的可选方案,当首选 bean 的数量超过一个时,无法进一步缩小可选范围。
Q:如何限定自动配置的 bean?
Spring 的限定符能够在所有可选的 bean 上进行缩小范围的操作,最终能够达到只有一个 bean 满足所规定的限制条件。A:@Qualifier 注解是使用限定符的主要方式。它可以与 @Autowired 和 @Inject 协同使用,在注入的时候指定想要注入进去的是哪个 bean。代码如下:
/** * 想要确保要将 IceCream 注入到 setDessert()之中。 * 这是使用限定符的最简单的例子。 * @param dessert */ @Autowired // 参数就是想要注入的 bean 的ID。 // @Qualifier("iceCream") 所引用的 bean 要具有 String 类型的"iceCream"作为限定符, // 所有的 bean 都会给定一个默认的限定符,这个限定符与 bean 的 ID 相同。 @Qualifier("iceCream") public void setDessert(Dessert dessert){ this.dessert = dessert; }
此时,方法上所指定的限定符与要注入的 bean 的名称是紧耦合的。
Q:如何创建自定义的限定符?
我们可以为 bean 设置自己的限定符,而不是依赖于将 bean ID 作为限定符。
A:在 bean 声明上添加 @Qualifier 注解。
/** * cold 限定符分配给了 IceCream bean * 此时,没有耦合类名,可以随意重构 IceCream 的类名,而不用担心会破坏自动装配。 */ @Component @Qualifier("cole") public class IceCream implements Dessert { } @Autowired // 注入的地方,引用 code 限定符即可。 @Qualifier("cole") public void setDessert(Dessert dessert){ this.dessert = dessert; }
// 当通过 Java 配置显示定义 bean 时,也可以与 @Bean 注解一起使用 @Bean @Qualifier("cold") public Dessert iceCream(){ return new IceCream(); }
为了能够使用多个限定符,我们需要自定义限定符注解。
Q:如何使用自定义的限定符注解?
A:
/** * 因为 Java 不允许在同一条目上重复出现相同类型的多个注解 * 所以使用自定义的 @Cold 来替换 @Qualifier("cold") * 它们具有了 @Qualifier 注解的特性。本身实际上就成为了限定符注解。 */ @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Cold { }
// 使用必要的限定符注解进行任意组合,从而将可选范围缩小到只有一个 bean 满足需求。 @Autowired @Cold @Creamy public void setDessert(Dessert dessert){ this.dessert = dessert; }
上一篇:高级装配 —— 条件化的 bean
下一篇:高级装配 —— 如何在不同的作用域中声明 bean?
相关文章推荐
- Spring 实战-第三章-处理自动装配的歧义性
- Spring-处理自动装配的歧义性
- Spring高级装配之处理自动化装配的歧义性
- 十四、处理自动装配的歧义性
- 《spring in action》--处理自动装配的歧义性
- 处理自动装配的歧义性
- SpringInAction 学习笔记:自动装配歧义性处理
- Spring-处理自动装配的歧义性
- Spring基础处理-自动装配的歧义性
- 处理自动装配的歧义性
- Spring journey -- 处理自动装配歧义性问题
- Spring-处理自动装配的歧义性
- 第四章 Spring.Net 如何管理您的类___对象的自动装配
- 如何在编译期进行拓扑排序,自动处理模块初始化依赖顺序。
- ASP.NET WebForm Form表单如何实现MVC那种“自动装配”效果呢?
- android webview如何处理自动提取手机号
- 具有自动截断功能的函数:对比:strcpy、strncpy、sprintf、snprintf在写入的数据大于缓冲区的情况下如何处理
- Spring MVC 自定义标签如何使用@Autowired自动装配注解
- ASP.NET WebForm Form表单如何实现MVC那种“自动装配”效果呢?
- tomcat配置文件自动还原,该如何处理