前言
咱們都知道在 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; } }