学而实习之 不亦乐乎

注解 @Autowired 和 @Resource 的使用、区别和选择

2024-01-15 22:35:22

一、@Autowired 和 @Resource

@Autowired和@Resource注解都可以在Spring应用中进行声明式的依赖注入。

1、@Autowired注解

@Autowired这个注解呢,是由Spring提供的,它可以用来对构造方法、成员变量以及方法参数上进行标注,能够根据对象类型完成自动注入。如下:

public class Service {

    //构造方法注入
    @Autowired
    public Service(Service service) {
        this.service = service;
    }

    //成员变量注入
    @Autowired
    private Service service;

    //方法参数注入
    @Autowired
    public void setService(Service service) {
        this.service = service;
    }
}

2、@Resource注解

它是由JDK提供的,遵循JSR-250规范,是JDK1.6及以上加入的新特性。作为Java的标准,它的作用和@Autowired无区别。与@Autowired不同的是它可以适用于所有的Java框架,而@Autowired只适用于Spring。简单的理解@Resource能够支持对象类型注入,也能够支持对象名称注入。

二、@Resource 和 @Autowired 的区别

那@Resource和@Autowired之间具体有哪些区别呢?我从以下五个方面来分析

1)、注解内部定义的参数不同

@Autowired只包含一个required参数,默认为true,表示开启自动注入。

public @interface Autowired {

    // 是否开启自动注入,不开启自动装配,可设为false。
    boolean required() default true;
}

而@Resource 包含七个参数,其中最重要的两个是name和type。

public @interface Resource {

    // bean的名称
    String name() default "";
    String lookup() default "";

    // Java类,被解析为bean的类型

    Class<?> type() default java.lang.Object.class;

    enum AuthenticationType {
        CONTAINER,
        APPLICATION
    }

    //身份验证类型
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;

    //组件是否可以与其他组件之间共享
    boolean shareable() default true;
    String mappedName() default "";

    //描述
    String description() default "";
}

2)、装配方式的默认值不同

@Autowired默认按type自动装配,而@Resource默认按name自动装配。当然,@Resource注解可以自定义选择,如果指定了name,则根据name自动装配,如果指定了type,则用type自动装配。

3)、注解应用的范围不同

@Autowired能够用在构造方法、成员变量、方法参数以及注解上,而@Resource能用在类、成员变量和方法参数上,这点从源码也能看得出来。

@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource { ... }

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired { ... }

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired { ... }

4)、出处不同

@Autowired是Spring定义的注解,而@Resource是遵循JSR-250规范,定义在JDK中。所以@Autowired只能在Spring框架下使用,而@Resource则可以与其他框架一起使用。

5)、装在顺序不同

@Autowired默认先按byType进行匹配,如果发现找到多个bean,则又按照byName方式进行匹配,如果还有多个,则报出异常。

而@Resource的装载顺序分为四种情况:

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常,具体流程如图所示:
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常,具体流程如图所示:
  3.  如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常,具体流程如图所示:
  4. 如果既没有指定name,也没有指定type,则自动按byName方式进行装配。如果没有匹配,则回退为按照类型进行匹配。

三、选择

虽然两者在功能上差别不大,使用起来也差不多。但是,在日常开发中,各有所爱。

有人建议使用 @Autowired,理由如下:

  • 第1:@Autowired功能略强大。支持优先注入、可以配置允许bean不存在。
  • 第2:若使用了Spring框架,使用其特有的注解个人感觉更好一点。
  • 第3:有人会认为@Resource更加通用,因为它是个规范,其他框架也会支持。但我认为,目前后端都是在用Spring了,没有必要考虑其他框架。

有人推荐 @Resource

如:@Resource (name="userService")

因为根据名字搜索是最快的,就好像查数据库一样,根据Id查找最快。因为这里的名字与数据库里面的ID是一样的作用。这个时候,就要求你多写几个名字,工作量自然就增加了。而如果你不用注解,用xml文件的时候,对于注入Bean的时候要求写一个Id,xml文件时候的id就相当于这里的名字。

@Autowired @Qualifie(“userService”) 也可以用名字,可是太长了。