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

 更新时间:2022年10月01日 09:39:58   作者:发则韩  
这篇文章主要介绍了Spring的@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。

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

相关文章

  • Spring Boot Dubbo 构建分布式服务的方法

    Spring Boot Dubbo 构建分布式服务的方法

    这篇文章主要介绍了Spring Boot Dubbo 构建分布式服务的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Java通过索引值实现约瑟夫环算法

    Java通过索引值实现约瑟夫环算法

    这篇文章主要介绍了Java通过索引值实现约瑟夫环,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • RabbitMQ使用SpringAMQP的配置方法

    RabbitMQ使用SpringAMQP的配置方法

    这篇文章主要介绍了RabbitMQ使用SpringAMQP的配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-03-03
  • Java使用正则表达式匹配获取链接地址的方法示例

    Java使用正则表达式匹配获取链接地址的方法示例

    这篇文章主要介绍了Java使用正则表达式匹配获取链接地址的方法,简单分析了java正则匹配常用方法及获取网址链接的相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • Java多线程之CAS机制详解

    Java多线程之CAS机制详解

    这篇文章主要介绍了Java多线程之CAS机制详解,CAS指的是Compare-And-Swap(比较与交换),它是一种多线程同步的技术,常用于实现无锁算法,从而提高多线程程序的性能和扩展性,需要的朋友可以参考下
    2023-07-07
  • Spring Boot 异步框架的使用详解

    Spring Boot 异步框架的使用详解

    这篇文章主要介绍了Spring Boot 异步框架的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • SpringBoot限制接口访问频率避坑

    SpringBoot限制接口访问频率避坑

    这篇文章主要为大家介绍了SpringBoot限制接口访问频率避坑,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Lombok如何快速构建JavaBean与日志输出

    Lombok如何快速构建JavaBean与日志输出

    这篇文章主要介绍了Lombok如何快速构建JavaBean与日志输出,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Spring Boot中快速操作Mongodb数据库指南

    Spring Boot中快速操作Mongodb数据库指南

    这篇文章主要给大家介绍了关于Spring Boot中如何快速操作Mongodb的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 利用Thumbnailator轻松实现图片缩放、旋转与加水印

    利用Thumbnailator轻松实现图片缩放、旋转与加水印

    java开发中经常遇到对图片的处理,JDK中也提供了对应的工具类,不过处理起来很麻烦,Thumbnailator是一个优秀的图片处理的开源Java类库,处理效果远比Java API的好,这篇文章主要介绍了利用Thumbnailator如何轻松的实现图片缩放、旋转与加水印,需要的朋友可以参考下
    2017-01-01

最新评论