天天看點

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

作者:老誠不bug

@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;
 
    }
}
           

再來看@Resource注解,代碼如下:

public class Service {
    
    @Resource(name = "service1")
    private Service service1;
    
    @Resource(name = "service2")
    private Service service2;
 

    @Reource
    private Service service3;
 
    @Reource
    private Service service4;

}
           

它是由JDK提供的,遵循JSR-250規範,是JDK 1.6及以上加入的新特性。作為Java的标準,它的作用和@Autowired無差別。與@Autowired不同的是,它适用于所有的Java架構,而@Autowired隻适用于Spring。讀者可以簡單地了解為,@Resource能夠支援對象類型注入,也能夠支援對象名稱注入。

@Resource和@Autowired之間具體有哪些差別呢?

可以從以下5個方面來分析。

1.注解内部定義的參數不同

@Autowired隻包含一個required參數,預設為true,表示開啟自動注入。

public @interface Autowired {

     // 是否開啟自動注入,在不開啟自動裝配時,可設為false

    boolean required() default true;
 
}
           

@Resource 包含7個參數,其中最重要的兩個是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({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired { ... }

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

4.出處不同

@Autowired是Spring定義的注解,而@Resource遵循JSR-250的規範,定義在JDK中。是以@Autowired隻能在Spring架構下使用,而@Resource則可以與其他架構一起使用。

5.裝配順序不同

@Autowired預設先與byType進行比對,如果發現找到多個Bean,則又按照byName方式進行比對,如果還有多個Bean,則報出異常。裝配順序如下圖所示。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

而@Resource的裝載順序分為如下4種情況。

1)如果同時指定name和type,則從Spring上下文中找到與它們唯一比對的Bean進行裝配,如果找不到則抛出異常,具體流程如下圖所示。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

2)如果指定name,則從上下文中查找與名稱(ID)比對的Bean進行裝配,如果找不到則抛出異常,具體流程如下圖所示。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

3)如果指定type,則從上下文中找到與類型比對的唯一Bean進行裝配,如果找不到或者找到多個就會抛出異常,具體流程如下圖所示。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

4)如果既沒有指定name,也沒有指定type,則自動按byName方式進行裝配。如果沒有比對成功,則仍按照type進行比對,具體流程如下圖所示。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

下面這張表可以幫助大家更好地了解和區分@Autowired和@Resource。

五個次元,解析 Spring 中 @Autowired 和 @Resource 的差別

總結一下,兩者在功能上差别不大,使用起來也差不多。但是,在日常開發中建議使用@Autowired,有以下3個理由。

  • @Autowired功能略強大。支援優先注入、可以配置允許Bean不存在。
  • 若使用Spring架構,則使用其特有的注解更好一點。
  • 有人認為@Resource更加通用,因為它是一個規範,其他架構也會支援。目前後端都在用Spring,沒有必要考慮其他架構。
面試點評:我們可以直接告訴面試官這兩個注解的差異,同時基于兩個注解的特性解釋更多的差異,這樣可以更好地展現自己對這方面知識的了解深度。面試官想考查求職者對Spring依賴注入方式的了解,以及對@Autowired和@Resource兩個注解底層實作方面的差別的了解。求職者在了解了底層實作的差異後,回答這個問題會比較容易。
來源:https://mp.weixin.qq.com/s/U3Rl1Eo-7riv-j2PlSpc7w

繼續閱讀