在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. AngularJS 笔记系列(五)过滤器 filter

    过滤器是用来格式化给用户展示的数据的. 在 HTML 中的模板绑定符号{{}} 内通过|符号来调用过滤器. 大写:{{ name | uppercase }} 也可以在 JS 中进行调用$filter ...

  2. etcd:从应用场景到实现原理的全方位解读 转自infoq

    转自 infoq etcd:从应用场景到实现原理的全方位解读 http://www.infoq.com/cn/articles/etcd-interpretation-application-scen ...

  3. H5 播放视频常见bug及解决方案

    本文摘自:本文来自“小时光茶社(Tech Teahouse)”公众号 原文:https://mp.weixin.qq.com/s/MM5ZwCiWLAeHalsNYMImnw 1. 自动播放问题 通过 ...

  4. Windows打开软件老是弹出无法验证发布者

    使用组策略管理器 gpedit.msc 用户配置-管理模板-Windows组件-附件管理器-中等风险文件类型的包含列表 .exe;.cmd;.bat;.js即可

  5. Nginx基础笔记

    压力测试工具:ab ab -n 请求数 -c 并发数 请求url Nginx: Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务. 特点 ...

  6. web.xml listener配置

    listener简介: <listener>能为web应用创建监视器,监听上下文的各种事件,如:application和session事件,这些监视器都是按相同的方式定义,它的功能取决于各 ...

  7. 创建squashfs

    SquashFS 通常的livecd都有一个这个文件,是核心的文件系统 SquashFS 也是一个只读的文件系统,它可以将整个文件系统压缩在一起,存放在某个设备,某个分区或者普通的文件中.如果您将其压 ...

  8. 20135302魏静静——linux课程第三周实验及总结

    linux课程第三周实验及总结 一.实验:跟踪分析Linux内核的启动过程 使用gdb跟踪调试内核从start_kernel到init进程启动 使用实验楼的虚拟机打开shell cd LinuxKer ...

  9. HTTP-java模拟Post请求小栗子

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  10. 【转】Python 字符串大小写转换

    转载自:python 中字符串大小写转换 一.pyhton字符串的大小写转换, 常用的有以下几种方法: 1.对字符串中所有字符(仅对字母有效)的大小写转换,有两个方法: print 'just to ...