聊聊依賴注入註解@Resource和@Autowired

1. 前言

@Resource@Autowired註解均可以在Spring Framework應用中進行聲明式的依賴注入。並且面試中常常涉及到這兩個註解的知識點。今天咱們來總結一下它們。html

2. @Resource

全稱javax.annotation.Resource,它屬於JSR-250規範的一個註解,包含Jakarta EEJ2EE)中。Spring提供了對該註解的支持。咱們來詳細瞭解一下該註解的規則。java

該註解使用在成員屬性和setter方法上。默認狀況下@Resource按照名稱注入,若是沒有顯式聲明名稱則按照變量名稱或者方法中對應的參數名稱進行注入。面試

Resource註解流程

若是咱們但願在目標Bean中體現多態咱們能夠這樣寫:spring

/**
 * 多態的體現.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class ResourceTest {
    @Resource
    private ApplicationRunner applicationRunner;    
    @Resource
    private ApplicationRunner runner;
    // ...
}
Qualifier 約束參見 Spring 註解 @Qualifier 詳細解析

3. @Autowired

@Autowired一般適用於構造函數,成員變量以及方法上。它的機制是這樣的:數組

Autowired流程

這個註解咱們是須要好好聊聊的,平常使用頻率至關高。app

3.1 標註在構造上

經過在目標Bean的構造函數上標註就能夠注入對應的Bean函數

package cn.felord;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * @author felord.cn
 * @since 9:26
 **/
@Component
public class AutowiredTest {
 private final ApplicationRunner applicationRunner;

    @Autowired
    public AutowiredTest(ApplicationRunner applicationRunner) {
        this.applicationRunner = applicationRunner;
    }
}
Spring Framework 4.3開始, @Autowired若是目標Bean只定義一個構造函數,則再也不須要在該構造函數上添加 @Autowired註解。若是目標Bean有幾個構造函數可用,而且沒有主/默認構造函數,則必須至少有一個構造函數被 @Autowired標記,以指示Spring IoC容器使用哪一個構造函數。

3.2 標註在成員變量上

@Resource同樣,@Autowired也能夠標註到目標Bean的成員變量上。ui

/**
 * @author felord.cn
 * @since 9:26
 **/
@Component
public class AutowiredTest {
    @Autowired
    private ApplicationRunner applicationRunner;
    
    // ...
    
}

3.3 標註到方法上

通常setter方法上使用的比較多。並且一個 @Autowired 支持注入多個參數。this

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {

    private ApplicationRunner applicationRunner;
    private EmployeeMapper employeeMapper;
    private DepartmentMapper departmentMapper;

    /**
     * Sets application runner.
     *
     * @param applicationRunner the application runner
     */
    @Autowired
    public void setApplicationRunner(ApplicationRunner applicationRunner) {
        this.applicationRunner = applicationRunner;
    }


    /**
     * 支持多參數
     *
     * @param employeeMapper   the employee mapper
     * @param departmentMapper the department mapper
     */
    @Autowired
    public void prepare(EmployeeMapper employeeMapper, DepartmentMapper departmentMapper) {
        this.employeeMapper = employeeMapper;
        this.departmentMapper = departmentMapper;
    }

}

你覺得這就完了?下面這種方式估計大多數人並無在乎過。spa

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
    // 注入 數組
    @Autowired
    private MovieCatalog[] movieCatalogs;
    
    private Map<String, Movie> movies;
    
    private Set<CustomerPreferenceDao> customerPreferenceDaos;
    
    // 注入 set
    @Autowired
    public MovieRecommender(Set<CustomerPreferenceDao> customerPreferenceDaos) {
        this.customerPreferenceDaos = customerPreferenceDaos;
    }
            
    // 注入 map 
    @Autowired
    public void setMovieCatalogs(Map<String, Movie> movies) {
        this.movies = movies;
    }
   
    // ...
}

能夠把Bean注入目標Bean的數組、集合容器中去。默認狀況下,當給定注入點沒有匹配的候選Bean可用時,自動裝配將失敗。至少應有一個匹配元素。

若是您但願元素按照特定順序排序,則元素Bean能夠實現 org.springframework.core.Ordered接口或者對應註解 @Order或標準 @Priority。基於某些機制不建議使用註解方式來排序,不然沒法達到預期指望,推薦使用接口 Ordered

3.4 裝配可選

@Resource沒有提供可選擇裝配的特性,一旦沒法裝配則會拋出異常;而@Autowired提供了required屬性(默認值爲true)以免這種狀況,設置@Autowiredfalse

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
    // 一旦找不到 movieFinder  不會異常  而初始化爲 null
    @Autowired(required = false)
    private MovieFinder movieFinder;
    // ...
}

這裏也有騷操做,你能夠忽略required屬性。經過 Java 8java.util.Optional來代表候選Bean可選。

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
public class SimpleMovieLister {
    // 使用 Optional 代表候選Bean可選
    @Autowired
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
     //   ...
    }
}

Spring 5.0開始,您還可使用@Nullable註解,這個註解能夠你本身實現檢測邏輯或者直接使用 JSR-305提供的javax.annotation.Nullable

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
public class SimpleMovieLister {
    // 使用 @Nullable 註解代表候選Bean可選
    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
      //  ...
    }
}

4. @Inject

Spring 3.0開始,Spring提供對JSR-330標準註解(依賴注入)的支持。 你須要引入依賴:

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

而後你就可使用相關的註解來進行依賴注入了,其中主要註解爲@javax.inject.Inject。大部分狀況下該註解均可以代替@Autowired使用,但@Inject沒有required屬性,不過它也能夠與java.util.Optional或使用@Nullable來達到一樣的效果。

大部分狀況下沒有人喜歡額外引入 Jakarta EE依賴來使用一個已經擁有的功能, Spring堵死了 Jakarta EE依賴注入的生態。

5. 總結

@Resource@Autowired的優先級順序不一樣(參見上圖),另外@Resource屬於 Jakarta EE規範而@Autowired屬於Spring範疇,@Resource沒法使用在構造參數中,@Autowired支持required屬性。從面向對象來講,@Resource更加適用於多態性的細粒度注入,而@Autowired更多專一於多態的單例注入。@Inject 則不必過多討論,只做爲一個添頭。好了今天就到這裏,多多關注:碼農小胖哥,更多幹貨知識分享。

關注公衆號:Felordcn 獲取更多資訊

我的博客:https://felord.cn

相關文章
相關標籤/搜索