爲何Spring推薦使用構造器注入而不是Field注入

前言

咱們都知道在 Spring Bean 的注入方式通常分爲三種:一、構造器注入 二、Setter注入 三、基於註解的 @Autowired 自動裝配(Field 注入)java

在以往的項目開發過程當中,咱們大多會使用方便靈活的 @Autowired 自動裝配的方式來管理依賴,可是 Spring 官方卻不推薦這麼作

spring

Inspection info: Spring Team recommends: 「Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies」.緩存

從上述信息中咱們能夠得知,Spring 團隊建議咱們使用構造注入的方式管理咱們的依賴,對強制依賴使用斷言,那麼爲何不建議使用自動裝配呢app

對比構造注入和Field注入

我麼能夠先來對比 Field 注入和 構造器注入的區別函數

Field 注入

// Field注入
public class AClass(){
    
    @Autowired`在這裏插入代碼片`
    private BClass BClass;
}

優勢

  • 代碼少,簡潔明瞭
  • 新增依賴十分方便,不須要修改原有代碼
  • 注入簡單,只須要使用 @Autowired 註解或者 @Resource 註解

缺點

  • 容易出現空指針異常,Field 注入容許構建對象實例的時候依賴的示例對象爲空,這就致使了空指針異常沒法儘早的暴露出來
  • 對單元測試不友好,若是使用 Field 注入,那麼進行單元測試就須要初始化整個Spring 環境,將全部 Bean 實例化
  • 會出現循環依賴的隱患
  • 容易破壞單一職責原則

構造器注入

// 構造器注入
public class AClass(){
    // 用 final 修飾,聽從依賴不可變原則
    private final BClass bClass;
    
   	public AClass(BClass bClass){
        this.bClass = bClass;
    }
}

優勢

  • 解決了依賴循環的問題(spring 的三層緩存機制)
  • 強依賴處理,在編譯階段就能暴露出問題
  • 方便單元測試
  • 能夠明確的指出依賴關係

缺點

  • 代碼冗餘,閱讀不友好

使用 Lombok 解決構造器注入代碼冗餘問題

針對構造器注入致使代碼過於繁重的問題,咱們能夠經過 lombok 插件來解決這個問題,使用lombok 的 @RequiredArgsConstructor註解生成一個包含全部常量的構造器單元測試

@RequiredArgsConstructor爲每一個須要特殊處理的字段生成一個帶有1個參數的構造函數。全部未初始化的final字段都將得到一個參數,以及任何標記爲@NonNull且未在聲明位置初始化的字段。對於那些用@NonNull標記的字段,還將生成顯式null檢查。若是用於標記爲@NonNull的字段的任何參數包含null,則構造函數將拋出NullPointerException。參數的順序與字段在類中出現的順序相匹配測試

@Service
@RequiredArgsConstructor
public class LogServiceImpl implements LogService {

    private final LogRepository logRepository;
    private final LogErrorMapper logErrorMapper;
}

// 實際效果等同於

@Service
public class LogServiceImpl implements LogService {

    private final LogRepository logRepository;
    private final LogErrorMapper logErrorMapper;
    
    public LogServiceImpl(final LogRepository logRepository, final LogErrorMapper logErrorMapper) {
        this.logRepository = logRepository;
        this.logErrorMapper = logErrorMapper;
    }
}
相關文章
相關標籤/搜索