你還在用@Autowired和@Resource?

語言: CN / TW / HK

theme: juejin

我正在參加「掘金·啟航計劃」

首先我不承認我的題目有虛假、誇大和引流的嫌疑,直接進入正題。

先透個底:我們在類上使用 Lombok的@RequiredArgsConstructor 註解來替代類中的多處@Autowired和@Resource

依賴注入

先回顧一下Spring的3種依賴注入。

  1. 屬性注入

``` public class SysUserController extends BaseController { @Autowired private ISysUserService userService;

@Resource
private ISysRoleService roleService;

} ```

@Autowired預設按型別裝配,@Resource預設按名稱裝配,當找不到與名稱匹配的bean時,才會按型別裝配。

而@Qualifier和Autowired配合使用,指定bean的名稱,也可以做到按名稱裝配。

IDEA中直接在變數上使用 @Autowired會發現警告提示:Field injection is not recommended

原因是官方建議我們使用構造器注入方式,這種方式存在明顯的弊端,比如:注入物件不能用final修飾、無法發現NullPointException的存在。

  1. 構造器注入

``` public class SysUserController extends BaseController {

private final ISysUserService userService;

private final ISysRoleService roleService;

public SysUserController(ISysUserService userService, ISysRoleService roleService) {
    this.userService = userService;
    this.roleService = roleService;
}

} ```

構造器依賴注入通過容器觸發一個類的構造器來實現的,通過強制指明依賴注入來保證這個類的執行,防止NullPointerException

Spring官方推薦使用構造器注入不僅是因為這種情況下成員屬性可以使用final關鍵字修飾,更關鍵的一點是能夠避免迴圈依賴,如果存在迴圈依賴,Spring專案啟動的時候就會報錯。

為什麼說是避免而不是解決呢?

因為構造器注入是通過構造方法來生成物件,其必須要先獲取屬性,才能生成呼叫構造方法進行例項化,這種情況的迴圈依賴是無法解決的。

下面通過一張圖來看下A、B倆相互依賴的物件注入方式不同時Spring能否解決迴圈依賴的情況:

構造器注入方式解決迴圈依賴:
1.程式碼重構
[email protected]註解
3.改用屬性注入
建議檢視:zhuanlan.zhihu.com

  1. Setter注入

``` public class SysUserController extends BaseController {

private ISysUserService userService;

@Autowired
public void setUserService(ISysUserService userService) {
    this.userService = userService;
}

} ```

需要注意的是,在使用Setter注入時需要加@Autowired@Resource註解,否則是無法注入成功的。

另外要注意一點,屬性注入和Setter注入的變數都無法使用final關鍵字修飾。

@RequiredArgsConstructor

這裡可能會有人說不推薦使用Lombok,只要我們知其然且知其所以然,那他就是一個幫助我們快速開發的好工具。

在說完Spring的三種依賴注入後,我們來認識一下Lombok的@RequiredArgsConstructor 註解。

在Lombok中,生成構造方法的註解一共有三個,分別是@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsContructor,我們這裡只介紹@RequiredArgsConstructor。

``` @Controller @RequiredArgsConstructor public class SysUserController extends BaseController {

private final ISysUserService userService;

private ISysRoleService roleService;

//---------------------------- } ```

使用@RequiredArgsConstructor會為我們生成一個包含常量、使用final關鍵字修飾的變數私有構造方法

那我們就可以不使用屬性注入(@Autowired和@Resource)的方式,直接通過構造器的方式來完成注入,不僅能夠省略簡化許多程式碼,也解決了屬性注入可能存在的空指標問題。