当候选 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. jmeter模拟对网站做压力测试

    一般的网站,在进入业务功能前先需登录,然后才能访问业务功能.基本框架如下 详细步骤: 1 .用badboy录制登录,访问随意一个网址. 2.用jmeter打开,一会自己写的时候可以参考里面的参数名称或 ...

  2. 【vijos】1746 小D的旅行(dijkstra)

    https://vijos.org/p/1746 这题就是水题.裸的跑完每个点的最短路后直接可以暴力出解.. 这题贴出来是因为我改了下我的dijkstra的模板...(其实是原来一直写错了233 注意 ...

  3. 修改Chem 3D模型的化学键属性的方法有哪些

    很多的用户在绘制化学图形过程中发现很多的图形都是立体结构的,这个时候就需要用Chem3D,它是ChemOffice的核心组件之一,在绘制立体模型和计算化学数据方面具有不可替代的作用.虽然ChemDra ...

  4. 【转】HDC,CDC,CWindowDC,CClientDC,CPaintDC等等

     转载出处:http://blog.sina.com.cn/s/blog_447611f20100lirt.html 首先说一下什么是DC(设备描述表) Windows应用程序通过为指定设备(屏幕,打 ...

  5. ReactJS组件之间通信

    http://www.open-open.com/lib/view/open1473838243065.html

  6. CSS-微信开放UI样式

    下面的链接是微信开放的CSS的样式: http://weui.github.io/weui/ 附上GitHub地址:https://github.com/weui/weui

  7. 【BZOJ3190】[JLOI2013]赛车 单调栈+几何

    [BZOJ3190][JLOI2013]赛车 Description 这里有一辆赛车比赛正在进行,赛场上一共有N辆车,分别称为个g1,g2……gn.赛道是一条无限长的直线.最初,gi位于距离起跑线前进 ...

  8. jQuery.each(object, [callback])数组对象操作--jQuery 对象访问 $().each(callback)

    jQuery.each(object, [callback]) 通用例遍方法,可用于例遍对象和数组. 不同于例遍 jQuery 对象的 $().each() 方法,此方法可用于例遍任何对象.回调函数拥 ...

  9. 160805、oracle查询:取出每组中的第一条记录

    在Java 9发布之前,我们来分享一些Java 8开发技巧 [以下为译文] 在使用JAVA 8进行开发多年后,结合个人使用IntelliJ IDEA的心得,我总结了以下几个JAVA8技巧供大家参考. ...

  10. Android Download机制详解(一)DocumentUI部分

    在Android中Google为我们集成了一套十分便利的Download机制,用来下载网络上的资源文件.以此省去了我们编写和维护大量与Download相关的代码. 组成 Android中Downloa ...