2016-10-06 84 views
30

我看過一些關於Spring MVCPortlets的帖子,建議不要使用字段注入。因爲我試圖得到一個所以我問自己,如果我使用現場注入,我無法回答它。據我瞭解領域注入是,如果你注入一個Bean成屬性與@Autowired這樣的:什麼是野外注射以及如何避免它?

CartController.java:

... 
@Autowired 
private Cart cart; 
... 

BookshopConfiguartion.java:

@Configuration 
public class BookShopConfiguration { 

@Bean 
public Cart cart(){ 
    return new Cart(); 
} 
//more configuration 

我的Cart.java用於存儲和提供有關購物車中的書。

在我的研究,我讀到構造函數注入

MyComponent.java:

... 
public class MyComponent{ 
private Cart cart; 

@Autowired 
public MyComponent(Cart cart){ 
    this.cart = cart; 
} 
... 

有什麼優點和這兩種類型的注射的的缺點是什麼?


編輯1:由於這個問題被標記爲this question重複我檢查。因爲在問題和答案中都沒有任何代碼示例,所以我不清楚我是否正確猜測了我正在使用哪種注入類型。

回答

70

注射類型

有三個選項的依賴性如何注入一個bean: 1.通過構造 2.通過制定者或其他方法 3.通過反射直接進入領域

您正在使用選項3 - 即在您的字段上直接使用@Autowired時。


注射準則

一般原則,as recommended also by Spring(見構造函數或基於二傳手-DI部分)如下:

  • 對於強制依賴或目標是不可改變的時候,使用構造函數注入
  • 對於可選或可改變的依賴性,使用setter注入
  • 大多數情況下避免現場注入。

字段注入缺點

爲什麼領域注入令人難以接受的原因有以下幾點:

  • 您不能創建一個不可改變的對象與構造函數注入
  • 你班有與DI容器緊密連接,不能在其外部使用
  • 您的類無法實例化(例如在單元測試中)而沒有反射。您需要DI容器實例化它們,這更像是集成測試
  • 真實依賴從外部隱藏,而不是體現在你的界面 - 構造函數或方法
  • 這是很容易有一個像10個依賴性。如果你正在使用構造函數注入,具有10個參數的構造函數將表明有些東西是可疑的。但是您可以無限期地使用字段注入添加註入字段。有太多的依賴關係是紅旗,該類通常不止一個事情,它可能違反單一責任原則。

結論

根據您的需求,您應主要使用構造器注入或構造函數和setter注入的一些組合。田間注射有許多缺點,應該避免。字段注入的唯一優點是編寫起來更方便,並不會超過所有的缺點。


進一步閱讀

我寫了一篇關於爲什麼通常不建議字段注入一個博客文章 - 你可以點擊此處查看 - Field Dependency Injection Considered Harmful

+4

這是一般不好的想法,並不好,告訴世界「應該避免現場注射」。顯示優點和反對意見,讓其他人自己決定;)許多人有其他經驗和自己的看待事物的方式。 – dit

+4

這裏可能就是這種情況,但還有其他一些情況是,社區已經達成普遍共識來勸阻某些事情。以匈牙利符號爲例。 – Jannik

+0

作爲可測試性和依賴關係可見性,您提供了一些優點,但我並不完全同意。構造函數注入沒有缺點?有5個或6個字段注入課堂上執行真正的呼叫組合是可取的。我不同意你的不變性。擁有最終字段並不是必須具有不可變的類。這是優選的。這是非常不同的。 – davidxxx

11

味道的問題。這是你的決定。

但我可以解釋一下,爲什麼我從來沒有用構造函數注入

  1. 我不希望實現一個構造爲我所有@Service@Repository@Controller豆。我的意思是,大約有40-50個豆或更多。每次如果我添加一個新的字段,我將不得不擴展構造函數。不,我不需要它,我不需要。

  2. 如果你的Bean(服務或控制器)需要注入很多其他bean,該怎麼辦?有8個參數的構造函數非常難看。

  3. 如果我使用CDI,構造函數不關心我。


編輯: Vojtech魯齊卡說:

類有太多的依賴,並可能違反單 責任原則,並應重構

是。理論與現實。 這裏是en示例:DashboardController映射到單個路徑*:8080/dashboard

我的DashboardController從其他服務中收集大量信息,將其顯示在儀表板/系統概述頁面中。我需要這個單一的控制器。所以我必須只保護這一條路徑(基本身份驗證或用戶角色過濾器)。

+10

具有8個依賴關係的非常醜陋的構造函數實際上很棒,因爲它是一個紅色標誌,表示某些錯誤,類具有太多的依賴關係,可能違反單個責任原則,應該重構。這實際上是一件好事。 –

+1

@VojtechRuzicka它確實不好,但有時你無法避免它。 – dit

+2

我會說3的經驗法則,更不用說40-50了,任何類的依賴都應該是你需要重構的標誌。有40個依賴關係的班級無法堅持單一責任主體或開放/關閉主體。 –

17

這是軟件開發中永無休止的討論之一,但業界主要影響者對這個話題越來越有見地,並開始建議構造函數注入作爲更好的選擇。

構造方法注入

優點:

  • 更好的可測試性。單元測試中不需要任何模擬庫或Spring上下文。您可以使用關鍵字新的創建要測試的對象。這樣的測試總是更快,因爲它們不依賴於反射機制。 (This question在30分鐘後被問到,如果作者使用了構造函數注入,它將不會出現)。
  • 不變性。一旦設置了依賴關係,就不能更改它們。
  • 更安全代碼。執行構造函數之後,您的對象就可以使用了,因爲您可以驗證作爲參數傳遞的任何內容。對象可以是準備好或不準備,中間沒有任何狀態。通過現場注入,您可以在物體易碎時引入中間步驟。
  • 清潔表達的強制性依賴關係。這方面的田間注射是不明確的。
  • 讓開發人員考慮設計。 dit寫了一個帶有8個參數的構造函數,這實際上是一個糟糕的設計和the God object anti-pattern的標誌。一個類在構造函數或字段中是否有8個依賴關係並不重要,它總是錯誤的。人們比通過字段更不願意向構造函數添加更多的依賴關係。它作爲向大腦發出的信號,表示您應該停下一段時間,並考慮一下代碼結構。

缺點:

  • 更多代碼(但現代的IDE減輕疼痛)。

基本上,注射是相反的。

相關問題