热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

autowire加载指定实现类_@Primary和@Qualifer注解当某个接口有多个实现类时,优先注入哪个类...

在spring中使用注解,常使用Autowired,默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会

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

@Primary和@Qualifer 注解的区别在于:

用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。

用@Qualifer告诉spring真正使用哪一个具体的实现。

下面是个简单的使用例子。

有如下一个接口

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

有下面的两个实现类:

48304ba5e6f9fe08f3fa1abda7d326ab.png

@Component // 加注解,让spring识别

public class MetalSinger implements Singer{

@Override

public String sing(String lyrics) {

return "I am singing with DIO voice: "+lyrics;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

//注意,这里没有注解

public class OperaSinger implements Singer {

@Override

public String sing(String lyrics) {

return "I am singing in Bocelli voice: "+lyrics;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

@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");

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

结果是什么呢?

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 可以闪亮登场了。

48304ba5e6f9fe08f3fa1abda7d326ab.png

@Primary

@Component

public class OperaSinger implements Singer{

@Override

public String sing(String lyrics) {

return "I am singing in Bocelli voice: "+lyrics;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

如果代码改成这样,再次运行,结果如下:

"I am singing in Bocelli voice: song lyrics", 用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。

二、@Qualifer注解

有如下接口:

public interface EmployeeService {

public EmployeeDto getEmployeeById(Long id);

}

同时有下述两个实现类 EmployeeServiceImpl和EmployeeServiceImpl1:

48304ba5e6f9fe08f3fa1abda7d326ab.png

@Service("service")

public class EmployeeServiceImpl implements EmployeeService {

public EmployeeDto getEmployeeById(Long id) {

return new EmployeeDto();

}

}

@Service("service1")

public class EmployeeServiceImpl1 implements EmployeeService {

public EmployeeDto getEmployeeById(Long id) {

return new EmployeeDto();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

调用代码如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

@Controller

@RequestMapping("/emplayee.do")

public class EmployeeInfoControl {

@Autowired

EmployeeService employeeService;

@RequestMapping(params = "method=showEmplayeeInfo")

public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) {

#略

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

在启动tomcat时报如下错误:

48304ba5e6f9fe08f3fa1abda7d326ab.png

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeInfoControl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.service.EmployeeService com.test.controller.EmployeeInfoControl.employeeService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.service.EmployeeService] is defined: expected single matching bean but found 2: [service1, service2]

48304ba5e6f9fe08f3fa1abda7d326ab.png

其实报错信息已经说得很明确了,在autoware时,由于有两个类实现了EmployeeService接口,所以Spring不知道应该绑定哪个实现类,所以抛出了如上错误。

这个时候就要用到@Qualifier注解了,qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!

48304ba5e6f9fe08f3fa1abda7d326ab.png

@Controller

@RequestMapping("/emplayee.do")

public class EmployeeInfoControl {

@Autowired

@Qualifier("service")

EmployeeService employeeService;

@RequestMapping(params = "method=showEmplayeeInfo")

public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) {

#略

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

问题解决!



推荐阅读
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • ScrollView嵌套Collectionview无痕衔接四向滚动,支持自定义TitleView
    本文介绍了如何实现ScrollView嵌套Collectionview无痕衔接四向滚动,并支持自定义TitleView。通过使用MainScrollView作为最底层,headView作为上部分,TitleView作为中间部分,Collectionview作为下面部分,实现了滚动效果。同时还介绍了使用runtime拦截_notifyDidScroll方法来实现滚动代理的方法。具体实现代码可以在github地址中找到。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
  • 本文详细介绍了使用C#实现Word模版打印的方案。包括添加COM引用、新建Word操作类、开启Word进程、加载模版文件等步骤。通过该方案可以实现C#对Word文档的打印功能。 ... [详细]
author-avatar
陈炘宇_573
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有