自動裝配協作者

Spring 容器可以自動裝配協作者(Collaborators)之間的關係。你可以讓 Spring 透過檢查 ApplicationContext 的內容,自動為你的 bean 解析協作者(其他 bean)。自動裝配具有以下優點:

  • 自動裝配可以顯著減少指定屬性或建構函式引數的需求。(本章其他地方討論過的 bean 模板等其他機制在這方面也很有價值。)

  • 自動裝配可以在物件演進時更新配置。例如,如果你需要向一個類新增依賴項,該依賴項可以自動滿足,而無需修改配置。因此,自動裝配在開發過程中特別有用,並且不排斥在程式碼庫變得更穩定時切換到顯式裝配的選項。

使用基於 XML 的配置元資料時(參見依賴注入),你可以透過 `` 元素的 autowire 屬性指定 bean 定義的自動裝配模式。自動裝配功能有四種模式。你可以為每個 bean 指定自動裝配,因此可以選擇哪些 bean 進行自動裝配。下表描述了四種自動裝配模式:

表 1. 自動裝配模式
模式 說明

no

(預設) 不進行自動裝配。Bean 引用必須由 ref 元素定義。對於大型部署,不建議更改此預設設定,因為顯式指定協作者提供了更好的控制和清晰度。在某種程度上,它記錄了系統的結構。

byName

按屬性名自動裝配。Spring 會查詢與需要自動裝配的屬性同名的 bean。例如,如果一個 bean 定義被設定為按名稱自動裝配,並且它包含一個 master 屬性(即它有一個 setMaster(..) 方法),Spring 會查詢名為 master 的 bean 定義並用它來設定該屬性。

byType

如果容器中存在 *正好一個* 屬性型別的 bean,則允許自動裝配該屬性。如果存在多個,則會丟擲致命異常,這表明你不能對該 bean 使用 byType 自動裝配。如果沒有匹配的 bean,則不會發生任何事情(屬性未設定)。

constructor

類似於 byType,但應用於建構函式引數。如果容器中不存在 *正好一個* 建構函式引數型別的 bean,則會引發致命錯誤。

使用 byTypeconstructor 自動裝配模式時,你可以裝配陣列和帶型別的集合。在這種情況下,容器中所有與期望型別匹配的自動裝配候選者都會被提供來滿足依賴。如果期望的鍵型別是 String,你可以自動裝配強型別的 Map 例項。自動裝配的 Map 例項的值包含所有匹配期望型別的 bean 例項,而 Map 例項的鍵包含相應的 bean 名稱。

自動裝配的限制和缺點

自動裝配在整個專案中一致使用時效果最佳。如果通常不使用自動裝配,而只對一兩個 bean 定義使用,可能會讓開發者感到困惑。

考慮自動裝配的限制和缺點:

  • propertyconstructor-arg 設定中的顯式依賴項總是會覆蓋自動裝配。你不能自動裝配基本型別、StringsClasses 等簡單屬性(以及這些簡單屬性的陣列)。此限制是設計使然。

  • 自動裝配不如顯式裝配精確。儘管正如前面表格中提到的,Spring 在可能出現意外結果的歧義情況下會謹慎地避免猜測。你的 Spring 管理的物件之間的關係不再被顯式地記錄。

  • 裝配資訊可能對從 Spring 容器生成文件的工具不可用。

  • 容器中的多個 bean 定義可能與 setter 方法或要自動裝配的建構函式引數指定的型別匹配。對於陣列、集合或 Map 例項,這不一定是個問題。然而,對於期望單個值的依賴項,這種歧義不會被隨意解決。如果沒有唯一的 bean 定義可用,則會丟擲異常。

在後一種情況下,你有幾種選擇:

  • 放棄自動裝配,轉而使用顯式裝配。

  • 透過將 bean 定義的 autowire-candidate 屬性設定為 false 來避免該 bean 的自動裝配,如下一節所述。

  • 透過將 `` 元素的 primary 屬性設定為 true,將單個 bean 定義指定為主要候選者。

  • 實現基於註解的配置提供的更細粒度的控制,如基於註解的容器配置中所述。

排除 Bean 的自動裝配

對於每個 bean,你可以將它排除在自動裝配之外。在 Spring 的 XML 格式中,將 `` 元素的 autowire-candidate 屬性設定為 false;對於 `@Bean` 註解,該屬性名為 autowireCandidate。容器會使該特定的 bean 定義對自動裝配基礎設施不可用,包括基於註解的注入點,例如 `@Autowired`

autowire-candidate 屬性旨在隻影響基於型別的自動裝配。它不影響按名稱進行的顯式引用,即使指定的 bean 未標記為自動裝配候選者,按名稱引用也會解析。因此,如果名稱匹配,按名稱自動裝配仍然會注入 bean。

你還可以根據 bean 名稱的模式匹配來限制自動裝配候選者。頂級 `` 元素在其 default-autowire-candidates 屬性中接受一個或多個模式。例如,要將自動裝配候選者狀態限制為名稱以 Repository 結尾的任何 bean,請提供 *Repository 的值。要提供多個模式,請將它們定義為逗號分隔的列表。對於 bean 定義的 autowire-candidate 屬性,明確的 truefalse 值總是優先。對於這些 bean,模式匹配規則不適用。

這些技術對於你永遠不想透過自動裝配注入到其他 bean 中的 bean 非常有用。這並不意味著被排除的 bean 本身不能使用自動裝配進行配置。而是說,該 bean 本身不是自動裝配其他 bean 的候選者。

從 6.2 版本開始,`@Bean` 方法支援自動裝配候選者標誌的兩種變體:`autowireCandidate` 和 `defaultCandidate`。

當使用限定符(qualifiers)時,標記為 `defaultCandidate=false` 的 bean 僅在存在額外限定符指示的注入點可用。這對於那些應該在特定區域可注入但又不希望影響其他位置同類型 bean 的受限委託非常有用。這樣的 bean 絕不會僅按宣告型別注入,而是按型別加上特定限定符注入。

相比之下,`autowireCandidate=false` 的行為與上面解釋的 `autowire-candidate` 屬性完全相同:這樣的 bean 將永遠不會按型別注入。