Spring 的依賴注入機制主要基於類型,而非名稱。當遇到多個相同類型的 Bean 時(例如 TenantDataSource),它不會自動回退到按參數名稱匹配。這是因為 Spring 無法始終保證方法中的參數名稱與 Bean 名稱匹配。
Java 默認情況下不會在編譯後的字節碼中保留參數名稱。如果沒有特殊配置,參數名稱(例如 tenantADataSource 和 tenantBDataSource)會在編譯期間被清除,並替換為通用的名稱,如 arg0 和 arg1。 因此,Spring 無法得知 tenantADataSource 指的是名為 "tenantA-dataSource" 的 Bean。
可以使用 -parameters
編譯器標誌來保留字節碼中的參數名稱:
<code>javac -parameters MyClass.java</code>
即使使用了此標誌,Spring 仍然不會按參數名稱匹配,除非明確配置。
Spring 避免做出假設以防止意外行為。例如,如果參數名稱意外交換或命名錯誤,或者開發人員期望不同的映射,會發生什麼? 如果沒有明確的指導(例如 @Qualifier
),Spring 無法確定開發人員的意圖,而選擇拋出錯誤,而不是可能注入錯誤的 Bean。
Spring 遵循“顯式優於隱式”的原則。依賴注入應該具有可預測性,並且不依賴於參數名稱到 Bean 名稱匹配之類的假設。 Spring 的運作方式在不同的環境和框架中保持一致。某些語言或框架(如 Kotlin)默認保留參數名稱,而其他語言則不保留,因此 Spring 避免依賴參數名稱來實現關鍵功能。
雖然 Spring 默認情況下不按參數名稱匹配,但在某些情況下可以按參數名稱匹配,但這取決於您的設置:
如果使用 -parameters
標誌編譯代碼,當存在歧義時,Spring 可以從參數名稱推斷 Bean 名稱。
<code>@Autowired public TenantService(TenantDataSource tenantADataSource, TenantDataSource tenantBDataSource) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; }</code>
如果使用了 -parameters
標誌並且參數名稱(tenantADataSource、tenantBDataSource)與 Bean 名稱匹配,Spring 可以解決歧義。但是,這種行為在復雜的配置中並不總是可靠或可預測的,這就是為什麼首選顯式配置(例如 @Qualifier
)。
使用 @Qualifier
可以確保清晰度並消除歧義,使開發人員和框架都能明確意圖。
<code>@Autowired public TenantService( @Qualifier("tenantA-dataSource") TenantDataSource tenantADataSource, @Qualifier("tenantB-dataSource") TenantDataSource tenantBDataSource ) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; }</code>
這樣,Spring 就能準確知道要注入哪些 Bean,而不管參數名稱或其他因素如何。
有人可能會認為像 Spring 這樣的框架應該更智能,並在存在歧義時自動將 Bean 名稱與參數名稱匹配。但是:
@Qualifier
)確保開發人員始終知道正在註入哪些 Bean。隱式假設可能會導致難以調試的問題,尤其是在大型複雜應用程序中。 在大多數實際應用程序中:
@Qualifier
這樣的顯式配置以確保清晰度。 @Qualifier
)來解決歧義。 -parameters
),Spring 也會避免隱式基於名稱的匹配,除非明確配置。 @Qualifier
或 @Primary
)而不是依賴於隱式匹配。 以上是春季 - 為什麼要逐名 - 擬議中的標準的詳細內容。更多資訊請關注PHP中文網其他相關文章!