為什麼不建議過度使用Spring 屬性注入依賴的方式?

Spring 支持的三種依賴注入方式


為什麼不建議過度使用Spring 屬性注入依賴的方式?

<code>// 屬性注入
@Autowired
private DependencyA dependencyA;/<code>

屬性注入的主要優點:添加依賴非常容易,代碼變短和簡潔,開發者不需要寫一堆setter或構造器方法,只需要關心業務邏輯即可。

<code>// Set注入
private DependencyA dependencyA;
@Autowired
public void setDependencyA(DependencyA dependencyA) {
    this.dependencyA = dependencyA;
}
// 構造器注入
private DependencyA dependencyA;
@Autowired
public DI(DependencyA dependencyA) {
    this.dependencyA = dependencyA;
}/<code>

相比於屬性注入,使用Set注入和構造器注入稍顯“繁瑣”,需要開發者編寫額外的方法代碼,並需要手動制定具體的依賴。從另一個角度來看,這種手動指定依賴的方式能夠允許我們動態改變依賴或至少使開發者更加明確系統的依賴設計,也不失為一種靈活性的表現。

過度使用屬性注入有什麼問題?

基於屬性依賴注入的方式本身沒有太大問題,但問題在於對其過度使用

SRP和重構關注的消失

屬性注入添加依賴太容易了,添加一個新的依賴成本很低,以至於開發者在新增依賴時降低了應有的設計思考,將依賴輕易加入到主類中,而缺失了重構的考量,並導致導致主類存在過多依賴,極易造成一個龐大的、臃腫的類,違反OOP的單一職責原則。

對測試造成障礙

受DI容器管理的類只是一個普通的java對象,能夠被獨立實例化。通過這種方式,可以在單元測試中實例化而不需要啟動DI容器去實例化它。如果沒有DI容器耦合,不管有沒有被DI容器管理,都可以實例化這個類,可以脫離spring的管理去操作這個類。使用new關鍵字創建對象時,如果當這個對象缺少一些必要的依賴,調用的時候就會出現空指針異常,這樣的類不能在DI容器(測試、其他模塊)之外重用,因為除了反射之外,沒有其他方法向它提供所需的依賴項。

當依賴比較多時,都寫在Set方法或構造器方法中會導致可維護性變差?

如果建議不使用屬性注入方式,而使用構造器或Set注入,開發者可能會存在這個問題:當依賴比較多時,都寫在Set方法或構造器方法中,參數列表太多,代碼的可維護性和可讀性都會變差怎麼辦

顯然,這是確實存在的問題。構造器注入和Set注入畢竟沒有屬性注入方式代碼簡潔,過多的參數確實會導致可讀性的下降,這是肯定會存在的現象,也確實是一中問題。但,當你觸發這種思考不正是建議使用構造器注入和Set注入所帶來的收益嗎?正是這種可讀性的下降,讓我們被動的觸發了關於類設計合理性的思考:這個類真的需要耦合這麼多依賴嗎?是否符合SRP原則呢?所以,如果違反了SRP原則我們需要進行重構設計進行拆分了。

最佳實踐

  • 大多數情況下應該避免使用屬性注入
  • Set注入用於解決可選依賴的場景
  • 構造器注入用於強制依賴的場景


分享到:


相關文章: