解讀為什么@Autowired在屬性上被警告,在setter方法上不被警告問題
在 Spring 開發(fā)中,@Autowired
注解常用于實現依賴注入。它可以應用于類的 屬性、構造器 或 setter 方法 上。然而,當 @Autowired
注解在 屬性 上使用時,IntelliJ IDEA 等 IDE 會給出 Field injection is not recommended
的警告,而在 setter 方法 上使用 @Autowired
時卻不會出現這個警告。
1. 為什么 @Autowired 在屬性上被警告?
1.1 隱式依賴注入
當 @Autowired
注解應用于類的 屬性 上時,Spring 會直接注入該屬性,而不通過構造函數或 setter 方法顯式地傳遞依賴項。
這種注入方式稱為 字段注入(Field Injection)。
字段注入 的缺點主要體現在以下幾個方面:
1.隱式依賴:
- 通過字段注入,類的依賴關系是隱式的,無法在類的構造器或方法中顯式地看到這些依賴。相對而言,構造器注入 和 setter 注入 可以使依賴關系更加明確。
- 由于字段依賴是隱式注入的,開發(fā)者很難在不查看容器配置的情況下,快速了解一個類的所有依賴項。
2.難以進行單元測試:
- 字段注入的屬性是隱式注入的,無法通過構造函數或 setter 方法顯式傳遞。在單元測試中,手動注入模擬(mock)對象時,需要通過反射或者測試框架自動注入,這增加了測試的復雜性。
- 與此相比,構造器注入和 setter 注入會使依賴關系顯式可見,能夠更方便地進行 單元測試。
3.違反依賴倒置原則(DIP):
- 在 依賴倒置原則 中,依賴關系應該通過 接口 或 抽象 進行注入,而不應該在類內部直接依賴于具體的實現。
- 字段注入使得類的依賴更加隱式,可能會增加代碼的耦合性。
1.2 IDE 的警告:Field injection is not recommended
IntelliJ IDEA 等 IDE 會根據這些設計缺點發(fā)出警告,提示 @Autowired
注解不推薦使用在屬性上。
字段注入的方式可能會導致代碼的可維護性差,容易出現一些潛在問題(如不清晰的依賴關系和難以測試的代碼)。
2. 為什么 @Autowired 在 setter 方法上不被警告?
當 @Autowired
用于 setter 方法 時,Spring 會通過 setter 注入 方式將依賴項注入到對象的屬性中。
與字段注入不同,setter 注入方式具有以下優(yōu)勢:
2.1 顯式依賴注入
顯式依賴關系:使用 setter 方法注入,開發(fā)者可以明確看到類所依賴的組件。通過查看類的 setter 方法,其他開發(fā)者可以輕松理解該類的依賴關系。
public class MyService { private MyRepository repository; @Autowired public void setRepository(MyRepository repository) { this.repository = repository; } }
符合依賴注入的設計原則:通過構造函數或 setter 方法注入依賴項,可以使類的依賴關系更加清晰,符合面向對象設計中的 依賴注入 和 單一職責原則。
2.2 可選的依賴注入
setter 注入適用于一些 可選依賴 的場景。如果某個依賴是可選的,可以通過 setter 方法來靈活注入,而不需要在構造器中強制要求依賴項的傳入。
@Autowired public void setOptionalDependency(Optional<Dependency> dependency) { this.dependency = dependency.orElse(null); }
2.3 易于測試
- 由于 setter 方法可以手動設置對象的依賴,因此它可以使單元測試變得更簡單。
- 你可以通過 setter 方法為對象注入模擬(mock)依賴項,而不需要通過反射等復雜手段。
MyService myService = new MyService(); myService.setRepository(mockRepository);
3. 構造器注入 vs 字段注入 vs Setter 注入
3.1 構造器注入(推薦)
構造器注入 是 最推薦的依賴注入方式,它具有以下優(yōu)勢:
- 強制依賴關系:通過構造器傳遞依賴項,可以確保所有的依賴項在對象創(chuàng)建時就已經被正確地注入。
- 不可變性:構造器注入使得依賴項在對象創(chuàng)建時就被初始化,避免了運行時更改依賴項。
- 易于測試:構造器注入使得所有的依賴項在構造時就顯式提供,便于進行單元測試。
public class MyService { private final MyRepository repository; @Autowired public MyService(MyRepository repository) { this.repository = repository; } }
3.2 Setter 注入(次推薦)
Setter 注入 是一個靈活的選擇,適用于依賴關系較為可選或后期可更改的場景。它具有以下特點:
- 靈活性:可以在對象創(chuàng)建后修改依賴項。
- 適用于可選依賴:如果某些依賴項是可選的,setter 注入能夠方便地管理。
public class MyService { private MyRepository repository; @Autowired public void setRepository(MyRepository repository) { this.repository = repository; } }
3.3 字段注入(不推薦)
字段注入 是最簡單的注入方式,但并不推薦使用,原因已在前面提到。字段注入具有以下缺點:
- 不清晰的依賴關系:依賴項通過字段注入,難以通過構造器或 setter 明確看到類的依賴。
- 難以測試:無法通過構造函數直接注入模擬對象,增加了單元測試的難度。
public class MyService { @Autowired private MyRepository repository; }
4. 總結
- 字段注入不推薦,因為它將依賴關系隱藏在字段中,難以清晰表達依賴項,增加了測試的復雜性。
- 推薦使用構造器注入,它提供了最強的類型安全性和不可變性,增強了代碼的可維護性和測試性。
- Setter 注入適用于可選依賴,但在依賴較多時容易導致依賴關系變得模糊,因此需要謹慎使用。
總體而言,使用構造器注入和 setter 注入能夠使代碼更清晰、易于維護,同時支持更好的單元測試。
如果 IDE 提示 Field injection is not recommended
,這意味著你可以考慮改用構造器注入或 setter 注入,以便提升代碼質量。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java ScheduledExecutorService的具體使用
ScheduledExecutorService有線程池的特性,也可以實現任務循環(huán)執(zhí)行,本文主要介紹了Java ScheduledExecutorService的具體使用,具有一定的參考價值,感興趣的可以了解一下2023-05-05基于Java和XxlCrawler獲取各城市月度天氣情況實踐分享
本文主要講解使用Java開發(fā)語言,使用XxlCrawler框架進行智能的某城市月度天氣抓取實踐開發(fā),文章首先介紹目標網站的相關頁面及目標數據的元素,然后講解在信息獲取過程的一些參數配置以及問題應對,需要的朋友可以參考下2024-05-05java開發(fā)ExecutorService監(jiān)控實現示例詳解
這篇文章主要為大家介紹了java開發(fā)ExecutorService監(jiān)控實現示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07Spring Boot集成LangChain來實現Rag應用的問題小結
檢索增強生成(RAG)是一種優(yōu)化大型語言模型(LLM)輸出的技術,通過引用權威知識庫以增強模型的準確性和相關性,RAG允許LLM在不重新訓練的情況下訪問特定領域的知識,提高了其在各種應用中的實用性和信任度,感興趣的朋友跟隨小編一起看看吧2024-09-09