一文搞懂Spring中@Autowired和@Resource的區別
@Autowired 和 @Resource 都是 Spring/Spring Boot 項目中,用來進行依賴註入的註解。它們都提供瞭將依賴對象註入到當前對象的功能,但二者卻有眾多不同,並且這也是常見的面試題之一,所以我們今天就來盤它。
@Autowired 和 @Resource 的區別主要體現在以下 5 點:
- 來源不同;
- 依賴查找的順序不同;
- 支持的參數不同;
- 依賴註入的用法不同;
- 編譯器 IDEA 的提示不同。
1.來源不同
@Autowired 和 @Resource 來自不同的“父類”,其中 @Autowired 是 Spring 定義的註解,而 @Resource 是 Java 定義的註解,它來自於 JSR-250(Java 250 規范提案)。
小知識:JSR 是 Java Specification Requests 的縮寫,意思是“Java 規范提案”。任何人都可以提交 JSR 給 Java 官方,但隻有最終確定的 JSR,才會以 JSR-XXX 的格式發佈,如 JSR-250,而被發佈的 JSR 就可以看作是 Java 語言的規范或標準。
2.依賴查找順序不同
依賴註入的功能,是通過先在 Spring IoC 容器中查找對象,再將對象註入引入到當前類中。而查找有分為兩種實現:按名稱(byName)查找或按類型(byType)查找,其中 @Autowired 和 @Resource 都是既使用瞭名稱查找又使用瞭類型查找,但二者進行查找的順序卻截然相反。
2.1 @Autowired 查找順序
@Autowired 是先根據類型(byType)查找,如果存在多個 Bean 再根據名稱(byName)進行查找,它的具體查找流程如下:
關於以上流程,可以通過查看 Spring 源碼中的
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 實現分析得出,源碼執行流程如下圖所示:
2.2 @Resource 查找順序
@Resource 是先根據名稱查找,如果(根據名稱)查找不到,再根據類型進行查找,它的具體流程如下圖所示:
關於以上流程可以在 Spring 源碼的 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessPropertyValues 中分析得出。雖然 @Resource 是 JSR-250 定義的,但是由 Spring 提供瞭具體實現,它的源碼實現如下:
2.3 查找順序小結
由上面的分析可以得出:
- @Autowired 先根據類型(byType)查找,如果存在多個(Bean)再根據名稱(byName)進行查找;
- @Resource 先根據名稱(byName)查找,如果(根據名稱)查找不到,再根據類型(byType)進行查找。
3.支持的參數不同
@Autowired 和 @Resource 在使用時都可以設置參數,比如給 @Resource 註解設置 name 和 type 參數,實現代碼如下:
@Resource(name = "userinfo", type = UserInfo.class) private UserInfo user;
但二者支持的參數以及參數的個數完全不同,其中 @Autowired 隻支持設置一個 required 的參數,而 @Resource 支持 7 個參數,支持的參數如下圖所示:
4.依賴註入的支持不同
@Autowired 和 @Resource 支持依賴註入的用法不同,常見依賴註入有以下 3 種實現:
- 屬性註入
- 構造方法註入
- Setter 註入
這 3 種實現註入的實現代碼如下。
a) 屬性註入
@RestController public class UserController { // 屬性註入 @Autowired private UserService userService; @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
b) 構造方法註入
@RestController public class UserController { // 構造方法註入 private UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
c) Setter 註入
@RestController public class UserController { // Setter 註入 private UserService userService; @Autowired public void setUserService(UserService userService) { this.userService = userService; } @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
其中, @Autowired 支持屬性註入、構造方法註入和 Setter 註入,而 @Resource 隻支持屬性註入和 Setter 註入,當使用 @Resource 實現構造方法註入時就會提示以下錯誤:
5.編譯器提示不同
當使用 IDEA 專業版在編寫依賴註入的代碼時,如果註入的是 Mapper 對象,那麼使用 @Autowired 編譯器會提示報錯信息,報錯內容如下圖所示:
雖然 IDEA 會出現報錯信息,但程序是可以正常執行的。
然後,我們再將依賴註入的註解更改為 @Resource 就不會出現報錯信息瞭,具體實現如下:
總結
@Autowired 和 @Resource 都是用來實現依賴註入的註解(在 Spring/Spring Boot 項目中),但二者卻有著 5 點不同:
- 來源不同:@Autowired 來自 Spring 框架,而 @Resource 來自於(Java)JSR-250;
- 依賴查找的順序不同:@Autowired 先根據類型再根據名稱查詢,而 @Resource 先根據名稱再根據類型查詢;
- 支持的參數不同:@Autowired 隻支持設置 1 個參數,而 @Resource 支持設置 7 個參數;
- 依賴註入的用法支持不同:@Autowired 既支持構造方法註入,又支持屬性註入和 Setter 註入,而 @Resource 隻支持屬性註入和 Setter 註入;
- 編譯器 IDEA 的提示不同:當註入 Mapper 對象時,使用 @Autowired 註解編譯器會提示錯誤,而使用 @Resource 註解則不會提示錯誤。
以上就是一文搞懂Spring中@Autowired和@Resource的區別的詳細內容,更多關於Spring @Autowired @Resource區別的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 深入分析@Resource和@Autowired註解區別
- 淺談spring DI 依賴註入方式和區別
- Spring中@Autowired與@Resource的區別詳析
- 關於@Autowierd && @Resource 你真的瞭解嗎
- Java面試題沖刺第十八天–Spring框架3