天天看點

你還在用@Autowired和@Resource來進行Bean注入麼?

作者:幽默的程式員面試寶典
你還在用@Autowired和@Resource來進行Bean注入麼?

在Spring中提供了三種依賴注入的方式,基于屬性注入、基于構造器注入、基于setter注入。但是在Lombok中提供了一種新的注入方式@RequiredArgsConstructor 下面我們就來詳細介紹一下。

依賴注入

屬性注入

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

    @Resource
    private ISysRoleService roleService;
}           

基于@Autowired預設是按照類型進行注入,如果沒有找到對應的類型則按照名稱注入。而@Resource則是先按照名稱進行注入,找不到對應的名稱的Bean的時候才會安裝類型進行注入。

而在Spring中還提供了一個@Qualifier 的注解與Autowired進行配合,用來指定名稱,進行裝配。

但是我們會發現如果在IDEA中在變量上直接使用了@Autowired 的注解會有一個Field injection is not recommended 的警告。原因就是官方會建議使用構造器進行注入,說明這種方式是存在弊端的。例如注入的對象不能用final修飾,無法發現空指針異常等等。

基于構造器注入

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

構造器注入的方式是通過容器觸發類的構造器函數來實作,通過強制指定某個依賴的方式來注入這個類的行為。這樣可以防止發生空指針的異常。

而Spring官方推薦使用構造器注入不僅是為了防止空指針,而且還可以進行如上代碼中所示的操作可以通過final關鍵字進行修飾。但是這都不是重點,重點是這種方式可以有效的避免循環依賴,如果這個時候,出現了循環依賴,那麼在Spring項目啟動的時候會出現報錯。

有人會問,循環依賴不是已經被前置處理器、後置處理器解決了麼?為什麼這裡說可以避免循環依賴呢?

這是因為構造器注入是通過構造方法來生成對象,其必須要先擷取屬性,才能生成調用構造方法進行執行個體化,這種情況的循環依賴是無法解決的。

構造器方式可以通過如下的幾種方式來解決循環依賴問題

  • 代碼重構
  • @Lasy注解
  • 改用屬性注入

Setter注入

public class SysUserController extends BaseController {
    
    private ISysUserService userService;

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

這種方式需要注意的是,在進行使用的時候需要添加@Autowired或者是@Resource的注解。否則是無法完成注入的。

另外需要注意的是通過setter和屬性的方式都是無法添加final關鍵字的。

@RequiredArgsConstructor

使用過Lombok的人一定知道這注解,但是也會有一部分人推薦不使用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關鍵字修飾的變量并且提供了對應的私有構造方法。

也就是說使用了@RequiredArgsConstructor注解之後,我們可以将上面三種注入方式所帶來的所有的優勢都進行了整合,這樣不但可以簡化很多的代碼,而且可以解決由于屬性注入所帶來的空指針的問題。