当候选 Bean 数目不为 1 时的应对方法

在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛出
BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。

 
我们可以来做一个实验:

清单 10. 候选 Bean 数目为 0 时

  1. <?xml version="1.0" encoding="UTF-8" ?>
  1. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">
  1. <bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor"/>
  1. <bean id="boss" class="com.baobaotao.Boss"/>
  1. <!-- 将 office Bean 注释掉 -->
  1. <!-- <bean id="office" class="com.baobaotao.Office">
  1. <property name="officeNo" value="001"/>
  1. </bean>-->
  1. <bean id="car" class="com.baobaotao.Car" scope="singleton">
  1. <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/>
  1. </bean>
  1. </beans>

由于 office Bean 被注释掉了,所以 Spring 容器中将没有类型为 Office 的 Bean了,而 Boss 的 office 属性标注了 @Autowired ,当启动 Spring 容器时,异常就产生了。

当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false) ,这等于告诉 Spring:在找不到匹配 Bean 时也不报错。来看一下具体的例子:

清单 11. 使用 @Autowired(required = false)

package com.baobaotao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Required;public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired(required = false) public void setOffice(Office office) { this.office = office; } …}

当然,一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。

和找不到一个类型匹配 Bean 相反的一个错误是:如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。来看下面的例子:

清单 12. 在 beans.xml 中配置两个 Office 类型的 Bean …

<bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/></bean><bean id="office2" class="com.baobaotao.Office"> <property name="officeNo" value="001"/></bean>…

我们在 Spring 容器中配置了两个类型为 Office 类型的 Bean,当对 Boss 的 office 
成员变量进行自动注入时,Spring 容器将无法确定到底要用哪一个 Bean,因此异常发生了。

Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:

清单 13. 使用 @Qualifier 注释指定注入 Bean 的名称

@Autowiredpublic void setOffice(@Qualifier("office")Office office) { this.office =office;}
@Qualifier("office") 中的 office 是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。正是由于注释对象的不同,所以 Spring 不将 @Autowired 和 @Qualifier 统一成一个注释类。

 
下面是对成员变量和构造函数入参进行注释的代码:

对成员变量进行注释:

清单 14. 对成员变量使用 @Qualifier 注释

这里的office也是在spring中配置的bean的ID,公司用的就是这个。

public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; …}

对构造函数入参进行注释:

清单 15. 对构造函数变量使用 @Qualifier 注释

public class Boss { private Car car; private Office office; @Autowired public Boss(Car car , @Qualifier("office")Office office){ this.car = car; this.office = office ; }}

@Qualifier 只能和 @Autowired 结合使用,是对 @Autowired 有益的补充。

 
一般来讲, @Qualifier 对方法签名中入参进行注释会降低代码的可读性,而对成员变量注释则相对好一些。
 
0

Spring @Qualifier l转的更多相关文章

  1. spring @qualifier注解

    1.spring @qualifier注解用来在spring按类型装配可能存在多个bean的情况下,@qualifier注解可以用来缩小范围或者指定唯一. 也可以用来指定方法参数 2.@qualifi ...

  2. spring @Qualifier注解使用

    @Autowired是根据类型进行自动装配的.如果当Spring上下文中存在多个UserDao类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在U ...

  3. Spring @Qualifier

    先说明下场景,代码如下: 有如下接口: public interface EmployeeService { public EmployeeDto getEmployeeById(Long id); ...

  4. Spring @Qualifier 注释

    可能会有这样一种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配. 在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指 ...

  5. Spring Autowiring @Qualifier example

    In Spring, @Qualifier means, which bean is qualify to autowired on a field. See following scenario : ...

  6. Spring 注解注入—@Qualifier 注释

    当创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean ...

  7. Spring 学习笔记一

    1.IOC,DI. 2.装配bean基于xml(实例化,声明周期,后处理bean,属性注入).3.装配bean基于注解 1       spring框架概述 1.1   什么是spring l  Sp ...

  8. Spring 框架(一)

    1 spring框架概述 1.1 什么是spring l Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert ...

  9. spring框架入门day01

    struts:web层,比较简单(ValueStack值栈,拦截器) hibernate:dao层,知识点杂 spring:service层,重要,讲多少用多少  --> [了解] spring ...

随机推荐

  1. python eval() hasattr() getattr() setattr() 函数使用方法详解

    eval() 函数 --- 将字符串str当成有效的表达式来求值并返回计算结果. 语法:eval(source[, globals[, locals]]) ---> value 参数: sour ...

  2. 《转》openstack中删除虚拟主机,状态一直deleting

    一.我重新启动了该机器.之后想删除没有创建成功的虚拟机(没有打开cpu的vt).结果发现状态一直为deleting状态.在这个状态下创建虚拟机也失败. 二.分析:在/var/log/nova/nova ...

  3. 微信小程序 事件

    事件详解 事件分类 事件分为冒泡事件和非冒泡事件: 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递. WXML的冒泡事件列 ...

  4. (转)使用.NET Reflector 查看Unity引擎里面的DLL文件

    当你查看unity里面API的时候,是不是有时候追踪了一两步就碰到DLL文件走不下去了呢?很是不爽吧. 这种问题我也是经常碰到.这是人家商业引擎不想让你看到底层代码啦,所以着急不得. 不过,今天我终于 ...

  5. mui 子页面切换父页面底部导航

    在父页面中新增方法: function switchTab(tab){ plus.webview.hide(activeTab); activeTab= tab; plus.webview.show( ...

  6. iOS-setNeedsLayout等布局方法

    列举下iOS layout的相关方法: layoutSubviews layoutIfNeeded setNeedsLayout setNeedsDisplay drawRect sizeThatFi ...

  7. hdu 2074 叠筐 好有意思的绘图题

    叠筐 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  8. JAVA基础面试(四4)

    31.String s = new String("xyz");创建了几个StringObject?是否可以继承String类? 两个或一个都有可能,”xyz”对应一个对象,这个对 ...

  9. 【原】storm源码之巧用java反射反序列化clojure的defrecord获取属性值

    storm源码是clojure.java.python的混合体.在解决storm-0.8.2的nimbus单点问题的过程中需要从zookeeper上读取目前storm集群中正在运行的assignmen ...

  10. because it violates the following Content Security Policy directive: "default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'". Note that 'script-src' was not explicitly set, so 'default-s

    html文件 修改成如下:<meta http-equiv="Content-Security-Policy" content="default-src *; st ...