在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary  的作用就出来了。下面是个简单的使用例子。

有如下一个接口

public interface Singer {
String sing(String lyrics);
}

有下面的两个实现类:

@Component // 加注解,让spring识别
public class MetalSinger implements Singer{ @Override
public String sing(String lyrics) {
return "I am singing with DIO voice: "+lyrics;
}
}
//注意,这里没有注解
public class OperaSinger implements Singer {
@Override
public String sing(String lyrics) {
return "I am singing in Bocelli voice: "+lyrics;
}
}

下面就是注入上面的接口实现类:

@Component
public class SingerService {
private static final Logger logger = LoggerFactory.getLogger(SingerService.class); @Autowired
private Singer singer; public String sing(){
return singer.sing("song lyrics");
}
}

结果是什么呢?
I am singing with DIO voice: song lyrics. 原因很简单,就是 OperaSinger 这个类上面根本没有加上注解@Copmonent 或者 @Service, 所以spring 注入的时候,只能找到 MetalSinger 这个实现类. 所以才有这个结果。

但是如果一旦 OperaSinger 这个类加上了@Copmonent 或者 @Service 注解,有趣的事情就会发生,你会发现一个错误的结果或异常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

提示很明确了,spring 根据类型无法选择到底注入哪一个。这个时候@Primay 可以闪亮登场了。

@Primary
@Component
public class OperaSinger implements Singer{ @Override
public String sing(String lyrics) {
return "I am singing in Bocelli voice: "+lyrics;
}
}

如果代码改成这样,再次运行,结果如下:
"I am singing in Bocelli voice: song lyrics", 用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。

二、用@Qualifier这个注解来解决问题

将上面的两个类改为如下:

@Component // 加注解,让spring识别
@Qualifier("metalSinger")
public class MetalSinger implements Singer{ @Override
public String sing(String lyrics) {
return "I am singing with DIO voice: "+lyrics;
}
}
@Component
@Qualifier("opreaSinger")
public class OperaSinger implements Singer {
@Override
public String sing(String lyrics) {
return "I am singing in Bocelli voice: "+lyrics;
}
}
@Component
public class SingerService {
private static final Logger logger = LoggerFactory.getLogger(SingerService.class); @Autowired
private Singer singer;

@Qualifier("opreaSinger")
public String sing(){
return singer.sing("song lyrics");
}
}

扩展:Spring注解常用汇总

使用注解之前要开启自动扫描功能

其中base-package为需要扫描的包(含子包)

<context:component-scan base-package="cn.test"/>
  • @Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
  • @Scope注解 作用域
  • @Lazy(true) 表示延迟初始化
  • @Service用于标注业务层组件、
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件。
  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
  • @Scope用于指定scope作用域的(用在类上)
  • @PostConstruct用于指定初始化方法(用在方法上)
  • @PreDestory用于指定销毁方法(用在方法上)
  • @Resource 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
  • @DependsOn:定义Bean初始化及销毁时的顺序
  • @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
  • @Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
  • @Autowired @Qualifier("personDaoBean") 存在多个实例配合使用
												

@Primary-在spring中常被忽视的注解的更多相关文章

  1. 在spring中常被忽视的注解 @Primary

    在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的. 但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary ...

  2. Spring中的@Valid 和 @Validated注解你用对了吗

    1.概述 本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 . 验证用户输入是否正确是我们应用程序中的常见功能.Spring提供了@Valid和@Validated两个注 ...

  3. Spring 中的事务操作、注解、以及 XML 配置

    事务 事务全称叫数据库事务,是数据库并发控制时的基本单位,它是一个操作集合,这些操作要么不执行,要么都执行,不可分割.例如我们的转账这个业务,就需要进行数据库事务的处理. 转账中至少会涉及到两条 SQ ...

  4. Spring中Bean管理的常用注解

    在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...

  5. Spring中通过java的@Valid注解和@ControllerAdvice实现全局异常处理。

    通过java原生的@Valid注解和spring的@ControllerAdvice和@ExceptionHandler实现全局异常处理的方法: controller中加入@Valid注解: @Req ...

  6. Spring中声明式事务的注解@Transactional的参数的总结(REQUIRED和REQUIRES_NEW的与主方法的回滚问题)

    一.事务的传播行为1.介绍 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.2.属性 事务的传播行为可以由传 ...

  7. Spring 中基于 AOP 的 @AspectJ注解实例

    @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格.通过在你的基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的 ...

  8. spring中xml配置方式和注解annoation方式(包括@autowired和@resource)的区别

    xml文件中配置itemSqlParameterSourceProvider是可以的: <bean id="billDbWriter" class="com.aa. ...

  9. 在使用spring中的ContextConfiguration、test注解时出现的错误

    错误: 在使用测试注解时出现ContextConfiguration注解和test注解无法正常导包使用的编译异常,如图: 解决办法: 将pom.xml文件中以下依赖管理 中的<scope> ...

随机推荐

  1. sqlserver 2005/2008 导入超大sql文件

    SQLCMD -E -dmaster -ic:\Scripts\create_db.sql 安装了Microsoft® SQL Server® 2008 R2 Native Client可用

  2. 转:js获取json中key所对应的value值

    <script type="text/javascript"> getJson('age'); function getJson(key){ var jsonObj={ ...

  3. HDU 1116 Play on Words(欧拉路径(回路))

    http://acm.hdu.edu.cn/showproblem.php?pid=1116 题意:判断n个单词是否可以相连成一条链或一个环,两个单词可以相连的条件是 前一个单词的最后一个字母和后一个 ...

  4. 斐迅面试记录—SSL和TLS的区别

    SSL 是洋文“Secure Sockets Layer”的缩写,中文叫做“安全套接层”.它是在上世纪90年代中期,由网景公司设计的.(顺便插一句,网景公司不光发明了 SSL,还发明了很多 Web 的 ...

  5. Java命令:Jstack

    jstack是java虚拟机自带的一种堆栈跟踪工具. 功能 jstack用于生成java虚拟机当前时刻的线程快照.线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目 ...

  6. $《Deep Work》思维导图读书笔记

    深度思考和深度工作能力已经成为当今如何应对知识爆炸.信息碎片化时代的一项重要技能,也是克服信息焦虑症的一剂良方.<Deep Work>这本书正是讲述如何一步步进入你的深度工作模式.

  7. Method Swizzling 剖析

    一.背景介绍 关于Method Swizzling的文章一大堆,讲的非常好的也数不胜数.不过,很多人只是会用,知道一些注意点.深入一点问的话,估计就答得不好.归其原因就是对Method Swizzli ...

  8. 测试应用documentFragment 和 直接操作dom 的区别

    DocumentFragment 节点不属于文档树,继承的 parentNode 属性总是 null. 不过它有一种特殊的行为,该行为使得它非常有用,即当请求把一个 DocumentFragment ...

  9. ODP.NET Oracle12.1版本免安装发布(IIS WebServices)

    1.ODP.NET必须的DLL OCI.DLL Oracle.DataAccess.dll OraOps12.dll msvcr100.dll oraociei12.dll oraons.dll 2. ...

  10. xxxx interview

    1. 什么数据库,做了什么优化? 回答mysql innodb与myisam区别,根据业务选择引擎.事务,行级锁,全文检索,二级索引. 存储:myisam数据和索引分开存储.innodb数据和索引存储 ...