1. 前言
@Resource
和@Autowired
註解都可以在Spring Framework應用中進行宣告式的依賴注入。而且面試中經常涉及到這兩個註解的知識點。今天我們來總結一下它們。
2. @Resource
全稱javax.annotation.Resource
,它屬於JSR-250規範的一個註解,包含Jakarta EE(J2EE)中。Spring提供了對該註解的支援。我們來詳細瞭解一下該註解的規則。
該註解使用在成員屬性和setter方法上。預設情況下@Resource
按照名稱注入,如果沒有顯式宣告名稱則按照變數名稱或者方法中對應的引數名稱進行注入。
如果我們希望在目標Bean中體現多型我們可以這樣寫:
/**
* 多型的體現.
*
* @author felord.cn
* @since 9 :26
*/
@Component
public class ResourceTest {
@Resource
private ApplicationRunner applicationRunner;
@Resource
private ApplicationRunner runner;
// ...
}
Qualifier 約束參見 Spring 註解 @Qualifier 詳細解析
3. @Autowired
@Autowired
通常適用於建構函式,成員變數以及方法上。它的機制是這樣的:
這個註解我們是需要好好聊聊的,日常使用頻率相當高。
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的成員變數上。
/**
* @author felord.cn
* @since 9:26
**/
@Component
public class AutowiredTest {
@Autowired
private ApplicationRunner applicationRunner;
// ...
}
3.3 標註到方法上
一般setter方法上使用的比較多。而且一個 @Autowired
支援注入多個引數。
/**
* 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;
}
}
你以為這就完了?下面這種方式估計大多數人並沒有在意過。
/**
* 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
)以避免這種情況,設定@Autowired
為false
。
/**
* The type Autowired test.
*
* @author felord.cn
* @since 9 :26
*/
@Component
public class AutowiredTest {
// 一旦找不到 movieFinder 不會異常 而初始化為 null
@Autowired(required = false)
private MovieFinder movieFinder;
// ...
}
這裡也有騷操作,你可以忽略required
屬性。通過 Java 8的 java.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 獲取更多資訊