• @Autowired与@Resource区别


    文章目录


    一、前言

    @Autowired和@Resource都是用来自动装配bean的。

    • @Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持。
    • @Autowired功能非常强大,但只适用于Spring框架,如果换成了JFinal等其他框架,功能就会失效。

    Spring Bean覆盖配置

    spring:
      main:
        allow-bean-definition-overriding: true
    
    • 1
    • 2
    • 3

    allow-bean-definition-overriding属性用于配置出现相同名称bean的情况如何处理:

    • 值为false时(默认值为false),如果出现相同名称的bean,直接抛异常。
    • 值为true时,表示支持相同名称的bean覆盖,后定义的bean会覆盖之前定义的相同名称的bean。

    下文会提到按类型装配,那么什么是同一类型呢?

    • 父类及其子类都属于父类这一类型
    • 接口及其实现类都属于接口这一类型

    二、@Autowired

    @Autowired是Spring提供的注解,用于自动装配。

    注解处理器

    AutowiredAnnotationBeanPostProcessor类是Autowired注解的注解处理器。

    关于注解处理器可参考文章:https://blog.csdn.net/JokerLJG/article/details/123548694

    装配方式

    • 按类型装配(默认使用的装配方式)。
    • 按名称装配(结合@Qualifier注解使用)。

    注解属性

    • required:默认值true。值为true时,表示必须注入,如bean不存在则会报错;值为false时,表示bean存在就注入,不存在则不注入。

    作用范围

    @Autowired的作用范围:成员变量、构造器、方法、参数、注解。

    1. 成员变量

    @Service
    public class UserService {
    
        @Autowired
        private IUser user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用最多的方式。

    2. 构造器

    @Service
    public class UserService {
    
        private IUser user;
    
        @Autowired
        public UserService(IUser user) {
            this.user = user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    构造器上使用Autowired注解,实际上还是使用了成员变量装配的方式,并非构造器装配。

    3. 方法

    @Service
    public class UserService {
    
        @Autowired
        public void test(IUser user) {
           user.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Spring会在项目启动的过程中,自动调用一次加了@Autowired注解的方法,我们可以在该方法做一些初始化的工作。

    4. 参数

    在构造器的入参上加Autowired注解

    @Service
    public class UserService {
    
        private IUser user;
    
        public UserService(@Autowired IUser user) {
            this.user = user;
            System.out.println("user:" + user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在非静态方法的入参上加Autowired注解

    @Service
    public class UserService {
    
        public void test(@Autowired IUser user) {
           user.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5. 注解

    略。

    使用技巧

    同一类型多个bean

    当按类型装配时,如果该类型的bean不止一个时,会直接报错。举例说明:

    接口:

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

    实现类1:

    @Service
    public class User1 implements IUser{
        @Override
        public void test() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实现类2:

    @Service
    public class User2 implements IUser{
        @Override
        public void test() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    自动装配:

    @Service
    public class UserService {
    
        @Autowired
        private IUser user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动时的错误信息:

    Field userService in com.joker.controller.UserController required a single bean, but 2 were found:
    	- userServiceImpl1: defined in file [D:workmyspringboot	argetclassescomjokercontrollerUserServiceImpl1.class]
    	- userServiceImpl2: defined in file [D:workmyspringboot	argetclassescomjokercontrollerUserServiceImpl2.class]
    
    • 1
    • 2
    • 3

    @Primary的使用

    @Primary注解可以解决上述问题(按类型装配时,如果该类型的bean不止一个时,会报错)。

    当我们使用自动配置的方式装配Bean时,如果这个Bean有多个候选者,假如其中一个候选者具有@Primary注解修饰,该候选者会被选中,作为自动装配的bean。

    在上面代码不变的情况下,只需在User1或User2上加@Primary注解,此时@Autowired自动装配会成功,并且自动装配的是加了@Primary注解的这个类对应的bean。

    User1类加@Primary注解

    @Service
    @Primary
    public class User1 implements IUser{
        @Override
        public void test() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    @Qualifier的使用

    通过@Autowired和@Qualifier的结合使用可以按名称装配。

    @Service
    public class UserService {
    
        @Autowired
        @Qualifier("user1")
        private IUser user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    自动装配名称为user1的bean(注意:bean的类型也必须要满足为IUser类型)。

    装配多个实例

    我们一般使用的都是用@Autowired自动装配单个实例,但其实它也可以用来装配多个实例。可以通过List、Set、Map来装配多个实例,如下:

    @Service
    public class UserService {
    
        @Autowired
        private List userList;
    
        @Autowired
        private Set userSet;
    
        @Autowired
        private Map userMap;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    上面的装配方式会吧IUser类型的多个实例bean都装配的List、Set、Map中。

    @Autowired装配未生效

    下面列举常见@Autowired装配未生效的情况:

    1. @Autowired所在类未加@Controller、@Service、@Component、@Repository等注解,或者或者一些其它情况(如直接new对象的到实例)。这些情况会导致该类的bean并没有交给spring容器去管理,spring就无法完成自动装配的功能。

      public class UserService {
      
          @Autowired
          private IUser user;
      
          public void test() {
              user.say();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    2. 注解未被@ComponentScan扫描到。

    三、@Resource

    @Resource是JDK自带的注解,用于自动装配。

    注解处理器

    CommonAnnotationBeanPostProcessor类是Resource的注解处理器。

    装配方式

    @Resource默认按照名称自动注入。

    • 既没指定name,也没指定type,自动按照名称装配(当注解写在字段上时,默认取字段名,当注解写在setter方法上时,默认取属性名进行装配。);如果没有匹配,则退而按照类型装配,找不到则抛出异常。

      如果没有指定 name 属性,

    • 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。

    • 如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。

    • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。

    注解属性

    Resource注解的主要属性:

    • name:指定需注入的bean的名称
    • type: 指定需注入的bean的类型

    作用范围

    @Resource的作用范围:类、成员变量、方法。

    1. 成员变量

    @Service
    public class UserService {
    
        @Resource
        private IUser user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 方法

    @Service
    public class UserService {
    
        @Resource
        public void test(IUser user) {
            user.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 类

    略。

    四、@Autowired与@Resource对比

    二者对比

    @Autowired

    @Resource

    Spring定义的注解

    JSR-250定义的注解

    默认按类型自动装配

    默认按名称自动装配

    一个参数:required(默认true),表示是否必须注入

    七个参数:最重要的两个参数是name、type

    默认按类型自动装配
    如果要按名称自动装配,需要使用@Qualifier一起配合

    默认按名称自动装配
    如果指定了name,则按名称自动装配;如果指定了type,则按类型自动装配

    作用范围:构造器、方法、参数、成员变量、注解

    作用范围:类、成员变量、方法

    @Autowired装配流程

    请添加图片描述

    @Resource装配流程

    请添加图片描述

  • 相关阅读:
    Julia两天极速入门学习笔记
    基于springboot的教师科研信息管理系统(含ssm版本)
    【物流推荐】HEGERLS堆垛机—自动化立体仓库中最重要的起重运输设备
    【技术美术知识储备】纹理基础2.0-凹凸映射
    怎样考过PMP?零经验的我这样做
    2023数维杯国际赛数学建模D题完整论文分享!
    Android 实现禁止复制
    记一次Tomcat卡死在 Deploying web application 步骤的问题
    论文解读-Early Detection of Cybersecurity Threats Using Collaborative Cognition
    串口转RS485:自动收发串口转RS485设计注意事项
  • 原文地址:https://blog.csdn.net/web18224617243/article/details/126030480