当候选 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. Java WEB应用开发

    B/S计算模式的3层架构: 软件设计与开发模式的演化 面向机器语言的开发模式 软件的生命周期开发模式 需求分析 系统设计 系统开发 系统测试 运行和维护 原型法开发模式 面向组件(Component) ...

  2. 《linux 内核全然剖析》 include/asm/io.h

    include/asm/io.h #define outb(value,port) \ __asm__ ("outb %%al,%%dx"::"a" (valu ...

  3. 读取csv格式的数据

    1.直接上代码,关键是会用 2.代码如下: <?php #添加推荐到英文站 $file = fopen('code.csv','r'); while ($data = fgetcsv($file ...

  4. Linux系统常用工具集

    整理Linux系统下一些日常工作中常用工具,旨在提高效率: 1.截图软件Shutter 2.通讯聊天工具pidgin 3.守护进程工具daemontools 4.远程桌面服务TigerVNC 5.Ma ...

  5. 【Raspberry Pi】读取DHT11温度湿度波折

    从网上找到了DHT11厂家说明书,尝试用python根据时序图写数据获取驱动,但发现python的高层特性导致在做底层代码时例如控制20us时延这类需求就没什么好的办法. 还是得回到C-wiringP ...

  6. SQLAllocStmt与SQLFreeStmt

    1.申请语句句柄 SQLAllocStmt函数为应用程序分配语句句柄,其格式为:RETCODE SQLAllocStmt(HDBC hdbc, HSTMT FAR * phstmt) 其中, hdbc ...

  7. poj 2531(dfs)

    题目链接:http://poj.org/problem?id=2531 思路:由于N才20,可以dfs爆搞,枚举所有的情况,复杂度为2^(n). #include<iostream> #i ...

  8. [LintCode] 二叉树的中序遍历

    The recursive solution is trivial and I omit it here. Iterative Solution using Stack (O(n) time and  ...

  9. linux禁用触摸板驱动

    Method 1: 终端输入如下命令: sudo modprobe -r psmouse 如果打开触摸板就是: sudo modprobe psmouse ------- Method 2: 第一步: ...

  10. 创建超小的Golang docker 镜像

    原文: http://colobu.com/2015/10/12/create-minimal-golang-docker-images/ 本文对于创建超小的镜像非常有用 Docker是PaaS供应商 ...