Spring的@Autowired加到接口上但获取的是实现类的问题

目录
  • @Autowired加到接口上但获取的是实现类
    • 问题
    • 为什么他会拿到userServiceImpl?
  • @Autowired一个接口有多个实现类
    • 例如

@Autowired加到接口上但获取的是实现类

问题

Spring的@Autowired加到接口上但获取的是实现类?

    /* 类 @Controller注解,会在spring容器中实例化对象 */
    @Controller
    public class UserContoller{
        @Autowired        // 先按类型找,然后按id为属性名去找
        private UserService userService;
        //为什么他会拿到userServiceImpl?
        // @Autowired会帮你按UserService的类型去容器中找唯一bean对象
        // 1、容器没有该类型的对象:报错
        // 2、容器中有该类型的唯一bean对象,就将该唯一bean对象赋值给该属性
        ///3、容器中有多个【两个及以上】该类型的唯一bean对象,
        //     它会再根据该属性名去容器中找,
        //     看看容器中的哪个bean对象的id值和该属性名一致,
        //     如果有,就将容器中该对象赋值给该属性,如果没有报错。
    }    
    /* 接口  */
    public interface UserService{}
    
    /* 类  @Service注解,会在spring容器中实例化对象 */
    @Service
    public class UserServiceImpl implements UserService{}

为什么他会拿到userServiceImpl?

@Autowired先按类型找,然后再按id为属性名去找

他会帮你按UserService的类型去容器中找唯一bean对象

  • 1.容器没有该类型的对象:报错
  • 2.容器中有该类型的唯一bean对象,就将该唯一bean对象赋值给该属性
  • 3.容器中有多个【两个及以上】该类型的唯一bean对象,

它会再根据该属性名去容器中找,看看容器中的哪个bean对象的id值和该属性名一致,如果有,就将容器中该对象赋值给该属性,如果没有报错。

然后通过多态的向上转型就赋值成功。等价于之前手动赋值

UserService userService = new UserServiceImpl();

@Autowired一个接口有多个实现类

@Autowired是spring的注解,默认使用的是byType的方式向Bean里面注入相应的Bean。

例如

@Autowired
private UserService userService;

这段代码会在初始化的时候,在spring容器中寻找一个类型为UserService的bean实体注入,关联到userService的引入上。

但是如果UserService这个接口存在多个实现类的时候,就会在spring注入的时候报错,具体如下:

public class UserService1 implements UserService
public class UserService2 implements UserService

当存多个UserService的实现类时,错误信息如下:

2016-08-05 14:53:53,795 ERROR [org.springframework.test.context.TestContextManager] - <Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@14a2f921] to prepare test instance [UserServiceTest@3c87521]>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserServiceTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private yjc.demo.service.UserService UserServiceTest.userService; nested exception is he[yjc.demo.service.UserService] is defined: expected single matching bean but found 2: userService1,userService2

抛出了org.springframework.beans.factory.BeanCreationException,而原因是注入的时候发现有2个匹配的bean,但是不知道要注入哪一个:expected single matching bean but found 2: userService1,userService2

那么如何应对多个实现类的场景呢,看一下代码:

@Autowired
private UserService userService1;
 
@Autowired
private UserService userService2;
 
@Autowired
@Qualifier(value = "userService2")
private UserService userService3;
 
@Test
public void test(){
         System.out.println(userService1.getClass().toString());
         System.out.println(userService2.getClass().toString());
         System.out.println(userService3.getClass().toString());
}

运行结果:

class yjc.demo.serviceImpl.UserService1
class yjc.demo.serviceImpl.UserService2
class yjc.demo.serviceImpl.UserService2

运行结果成功,说明了2种处理多个实现类的方法:

1.变量名用userService1,userService2,而不是userService。

通常情况下@Autowired是通过byType的方法注入的,可是在多个实现类的时候,byType的方式不再是唯一,而需要通过byName的方式来注入,而这个name默认就是根据变量名来的。

2.通过@Qualifier注解来指明使用哪一个实现类,实际上也是通过byName的方式实现。

由此看来,@Autowired注解到底使用byType还是byName,其实是存在一定策略的,也就是有优先级。优先用byType,而后是byName。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 聊聊@Autowired注解注入,写接口名字还是实现类的名字

    目录 用@Autowired注解注入,写接口名字还是实现类的名字 来自某程序员一个问答问题 Spring中Autowired注入接口的几个问题 1.Spring怎么知道注入哪个实现? 2.需要@Qualifier和@Resource注解吗? 3.为什么@Autowired使用在interface上而不是实现类上? 用@Autowired注解注入,写接口名字还是实现类的名字 来自某程序员一个问答问题 1. 有一点没明白,为什么注解@repository注解的是接口UserDAO的实现类UserDA

  • SpringBoot使用@Autowired为多实现的接口注入依赖

    目录 使用@Autowired为多实现的接口注入依赖 问题描述 方法一:使用@Qualifier限定 方法二:利用@Autowired可以byName匹配Bean的特性 方法三:使用@Primay 一个接口多个实现类的Spring注入 1. 首先, Interface1 接口有两个实现类 2. 通过 @Autowired 和 @Qualifier 配合注入 3. 使用@Resource注入,根据默认类名区分 4. 使用@Resource注入,根据@Service指定的名称区分 使用@Autowi

  • 详解Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理

    一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byType的,如果存在多个同一类型的bean,则使用@Qualifier来指定注入哪个beanName的bean. 与JDK的@Resource的区别:@Resource是基于bean的名字,即beanName,来从spring的IOC容器查找bean注入的,而@Autowried是基于类型byType

  • Spring详细讲解@Autowired注解

    目录 java注解 spring注解 (1)配置文件形式 (2)注解形式 @Autowired的解析 @Autowired的生效流程 java注解 在解释spring的注解之前,先了解一下什么是java的注解?:Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制. Java中类.变量.参数. 包等都可以添加注解,java的注解可以通过反射来获取到标注的内容,在编译器生成字节码文件时,标注信息也添加进去.当运行时,JVM可以根据标注信息获取相应的信息.

  • Spring注解@Autowired背后实现的原理

    目录 前言 使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式. spring技术自身也在不断的发展和改变,从当前springboot的火热程度来看,java config的应用是越来越广泛了,在使用java config的过程当中,我们不可避免的会有各种各样的注解打交道,其中,我们使用最多的注解应该就是@Autowired注解了.这个注解的功能就是为我们注入一个定义好的bean. 那么,这个注解除了我们常用的属性注入方式之外还有哪些使用方式呢?它

  • Spring的@Autowired加到接口上但获取的是实现类的问题

    目录 @Autowired加到接口上但获取的是实现类 问题 为什么他会拿到userServiceImpl? @Autowired一个接口有多个实现类 例如 @Autowired加到接口上但获取的是实现类 问题 Spring的@Autowired加到接口上但获取的是实现类?     /* 类 @Controller注解,会在spring容器中实例化对象 */     @Controller     public class UserContoller{         @Autowired    

  • 详解Spring注解--@Autowired、@Resource和@Service

    什么是注解 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文件,那么.xml文件又会非常多.总之这将导致配置文件的可读性与可维护性变得很低 2.在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率 为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java

  • Spring boot + LayIM + t-io 实现文件上传、 监听用户状态的实例代码

    前言 今天的主要内容是:LayIM消息中图片,文件的上传对接.用户状态的监听.群在线人数的监听.下面我将挨个介绍. 图片上传 关于Spring boot中的文件上传的博客很多,我也是摘抄了部分代码.上传部分简单介绍,主要介绍在开发过程中遇到的问题.首先我们看一下LayIM的相应的接口: layim.config({ //上传图片接口 ,uploadImage: {url: '/upload/file'} //上传文件接口 ,uploadFile: {url: '/upload/file'} //

  • 在Spring Boot中加载XML配置的完整步骤

    开篇 在SpringBoot中我们通常都是基于注解来开发的,实话说其实这个功能比较鸡肋,但是,SpringBoot中还是能做到的.所以用不用是一回事,会不会又是另外一回事. 涛锅锅在个人能力能掌握的范围之内,一般是会得越多越好,都是细小的积累,发生质的改变,所以今天和小伙伴们一起分享一下. 实践 1.首先我们新建一个SpringBoot Project ,工程名为 xml 2.添加web依赖,点击Finish完成构建 3.我们新建一个类 SayHello 不做任何配置 package org.t

  • 理解Java注解及Spring的@Autowired是如何实现的

    首先我们可以自己写一个注解: @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AnnoSample { String value(); } 注解使用 @interface来标识.这个注解定义了一个属性value,只能作用于方法上,生命周期是运行时. @Target用于指定可以放置注解的位置,这里指定的METHOD说明该注解只能放置到方法上面,还可以指定TYPE(类.接口.枚举类),

  • 解决@Autowired注入static接口的问题

    目录 @Autowired注入static接口问题 @Autowired自动注入普通service很方便 但是如果注入static修饰的service则注入不了 后来网上百度了一下,看到了一个方法 标签解释 导致@Autowired注入失败的问题 背景 原因 @Autowired注入static接口问题 @Autowired自动注入普通service很方便 如: @Component public class WarningMatterUtil { //报警表 @Autowired privat

  • Spring Security权限管理实现接口动态权限控制

    SpringBoot实战电商项目mall(30k+star)地址:https://github.com/macrozheng/mall 摘要 权限控管理作为后台管理系统中必要的功能,mall项目中结合Spring Security实现了基于路径的动态权限控制,可以对后台接口访问进行细粒度的控制,今天我们来讲下它的后端实现原理. 前置知识 学习本文需要一些Spring Security的知识,对Spring Security不太了解的朋友可以看下以下文章. mall整合SpringSecurity

  • Spring Security代码实现JWT接口权限授予与校验功能

    通过笔者前两篇文章的说明,相信大家已经知道JWT是什么,怎么用,该如何结合Spring Security使用.那么本节就用代码来具体的实现一下JWT登录认证及鉴权的流程. 一.环境准备工作 建立Spring Boot项目并集成了Spring Security,项目可以正常启动 通过controller写一个HTTP的GET方法服务接口,比如:"/hello" 实现最基本的动态数据验证及权限分配,即实现UserDetailsService接口和UserDetails接口.这两个接口都是向

  • Spring boot集成Go-FastDFS实现图片上传删除等功能实现

    一.背景 工作中接触到需要采集并管理大量图片的需求,本来是用的FastDFS,但是发现实际情况是在项目实施时难以找到linux服务器去安装FastDFS,所以经过调研,选择了可以在windows服务器上安装部署的Go-FastDFS文件服务器 二.Go-FastDFS简介 go-fastdfs是一个基于http协议的分布式文件系统,它基于大道至简的设计理念,一切从简设计,使得它的运维及扩展变得更加简单,它具有高性能.高可靠.无中心.免维护等优点. 三.安装Go-FastDFS文件服务器 1)下载

  • Spring Boot项目中实现文件上传功能的示例

    在实际项目中,文件上传是很多项目必不可少的一个功能.那么在 Spring Boot 项目中又是如何来实现文件上传功能的呢?一般来说,上传的文件可以保存到项目根目录下的某一文件夹中,但这样做显然是不太合适的.因此我们选择将文件上传到专门的文件服务器中.很多云计算厂商都提供文件存储服务.这里我选择的是阿里云的对象存储(OSS). 一.配置OSS 1. 导入SDK 首先,你需要注册阿里云的账号并开通对象存储服务.在准备工作完成之后,需要导入 JAVA 版本的 SDK,这里使用 maven 进行导入 <

随机推荐