• 【springboot】你了解@Autowired 和 @Resource吗?@Autowired 和 @Resource深入分析


    我们在开发中,一直用到的都是@Autowired,那么为什么这么用有没有想过?还有@Resource也可以作为注入的注解,为什么又不用?

    “认祖归宗”–@Autowired 和 @Resource来源

    那么首先,我们得知道这两个注解,他们是来自于哪?
    @Autowired

    package org.springframework.beans.factory.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
        boolean required() default true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    我们可以看到,它是package org.springframework.beans.factory.annotation;是一个 spring 的注解 ;

    @Resource

    package javax.annotation;
    
    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.RetentionPolicy.*;
    
    @Target({TYPE, FIELD, METHOD})
    @Retention(RUNTIME)
    public @interface Resource {
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们可以看到它是package javax.annotation;, 是一个J2EE (java自己)的注解。

    总结

    @Autowired 是一个 spring 的注解
    @Resource 是一个J2EE (java自己)的注解

    “通过现象看本质”–@Autowired 和 @Resource作用和区别

    1.现象一:一个业务接口只对应一个业务实现类

    UserService接口:

    public interface User Service{
     public void test();
    }
    
    • 1
    • 2
    • 3

    接口的实现类UserServiceImpl:

    @Service
    public class UserServieImpl implements UserService{
    @Override
    public void test()[
    	System.out.print("test");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    接下来我们给UserController里注入属性UserService
    分别使用@Autorwired以及@Resource

    ...
    @Autowired
    private UserService userService;
    ...
    
    • 1
    • 2
    • 3
    • 4
    ...
    @Resource
    private UserService userService;
    ...
    
    • 1
    • 2
    • 3
    • 4

    运行测试,结果都可以正常输出!

    难道这么说它们两个随便用??

    2.现象二:一个业务接口 对应 两个或多个业务实现类

    我们加上一个UserServiceImpl2实现类:

    @Service
    public class UserServieImpl2 implements UserService{
    @Override
    public void test()[
       System.out.print("test");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    现在,UserService接口有两个实现类,UserServiceImpl、UserServiceImpl2.

    继续!!!

    我们先使用@Autorwired注入!

    ...
    @Autowired
    private UserService userService;
    ...
    
    • 1
    • 2
    • 3
    • 4

    运行结果!出错!

    在这里插入图片描述

    报错信息显示:

    1. 告诉我们 ,在MyTestController里面, 需要注入一个UserService (实现类), 但是却发现了两个这种类型的bean。

    2. 提供解决思路, 告诉我们可以使用@Primay注解 告诉哪一个是优先注入的,或者 使用@Qualifier 指定一下 需要注入哪个。

    原因:

         @Autowired 是根据 类型 (byType)注入的 ,然后在找到type类型的bean时,如果发现有异常(不唯一等),会再去根据name去找bean注入。
        因为两个实现类bean都实现了UserService ,那肯定找到两个了,也就是有异常了,然后name我们写的是userService(实际两个业务实现类我们用@Service丢到spring容器里面默认名字是首字母小写userServiceImpl,userServiceImpl2),根本没有userService这个Bean。

    异常处理

    我们常配合 @Qualifier 注解去使用 ,指定一下 根据指定别名去注入。

    @Service("userService")
    public class UserServieImpl implements UserService{
    @Override
    public void test()[
    	System.out.print("test");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    ...
    @Autowired
    @Qualifier("userService")
    private UserService userService;
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样就可以解决 一个业务接口 对应 两个或多个业务实现类 的场景!!

    总结

    @Autowired 是根据 类型 (byType)注入的 , 然后当找到type类型的bean时,如果发现有异常(不唯一等),会再去根据name去找bean注入。


    接下来,我们换成@Resource注解!

    结果是:如同上面报错信息,也提示错误!

    原因

    @Resource 默认是 根据 名字(byName)注入的 。

    而且 @Resource 其实提供了 name 和 type 属性值设置。
    但是如果使用的时候,跟上文一样啥都没有指定,那么就是先byName 默认方式去找(userService):

    • 发现根本没有这个userService, 因为我们 注入到bean容器里面 是 这两个玩意(@Servcie):userServiceImpl、userServiceimpl2!

    • 而且咱们使用@Servcie 注入这俩玩意没有起别名,那么就是默认 首字母变小写 当做注入的bean名字。

    1. 那么 @Resource ,它根据可靠信息 name 名称 ( userService ),找不到bean;
    2. 那么就会根据 type 类型 (UserService) 去spring容器里面找找,有没有这种类型的bean;
      结果发现了 两个类型都是 UserService 的 两个倒霉孩子 userServiceImpl,userServiceImpl2 ;

    所以就报错!!!

    异常处理

    @Resource 人家默认 byName 去找bean ,然后还提供name 和type 一起设置或者单一设置。
    也就是说,这个@Resource 已经做得很到位了。

        简单解决,设置名字咯,刚刚说了 我们使用@Service 注入实现类bean的时候,没有特意指定名称,那么就是首字母小写当做了bean的名称,所以我们使用@Resource 也指定设置一下name:

    ...
    @Resource(name = "userService")
    private UserService userService;
    ...
    
    • 1
    • 2
    • 3
    • 4

    这样一来,就解决了@Resource的这种bean冲突问题!

    总结

    @Resource 默认是根据 ByName注入的 , 然后如果发现有异常(不唯一等),会再去根据type去找bean注入。同时,提供了name、type两个属性可以进行指定name或者type

    至此,这两个注解用法大家应该有所感受了吧!

  • 相关阅读:
    ATmega328P加硬件看门狗MAX824L看门狗
    科技改变视听4K 120HZ高刷新率的投影、电视、电影终有用武之地
    LOAM框架后端优化总结
    【车载AI音视频电脑】高清车载摄像头,车载云台摄像头
    【Elasticsearch教程18】Mapping字段类型之text 以及term、match和analyzer
    Java8新特性之新日期时间API
    建模规范:命名规范
    Camunda 7.x 系列【57】流程设计器
    编译pycaffe过程中遇到的问题及解决
    带你深入了解git
  • 原文地址:https://blog.csdn.net/weixin_43431218/article/details/127789108