Spring依賴注入DI之三種依賴注入類型詳解
Spring依賴注入
字段注入
首先,我們可以使用字段注入。想要在一個類中通過字段的形式注入某個對象,可以采用這樣的方式:
public class ClientService { @Autowired private HealthRecordService healthRecordService; public void recordUserHealthData() { healthRecordService.recordUserHealthData(); } }
可以看到,通過 @Autowired 注解,字段注入的實現(xiàn)方式非常簡單而直接,代碼的可讀性也很強。事實上,字段注入是三種注入方式中最常用、也是最容易使用的一種。但它也是三種注入方式中最應(yīng)該避免使用的。就像開篇說的,我們在 IDEA 中使用字段注入時會遇到“Field injection is not recommended”的提示。你知道為什么嗎?原因有三點。
問題一、
字段注入的最大問題是對象的外部可見性。在前面的 ClientService 類中,我們通過定義一個私有變量 HealthRecordService 來注入該接口的實例。顯然,這個實例只能在 ClientService 類中被訪問,脫離了容器環(huán)境我們無法訪問這個實例,來看下面這段代碼:
ClientService clientService = new ClientService(); clientService.recordUserHealthData ();
執(zhí)行這段代碼的結(jié)果就是拋出一個 NullPointerException 空指針異常,原因就在于無法在 ClientService 的外部實例化 HealthRecordService 對象。采用字段注入,類與容器的耦合度過高,我們無法脫離容器來使用目標對象。如果編寫測試用例來驗證 ClientService 類的正確性,那么想要使用 HealthRecordService 對象,就只能使用反射的方式,這種做法實際上是不符合 JavaBean 開發(fā)規(guī)范的,而且可能一直無法發(fā)現(xiàn)空指針異常的存在。
問題二、
我們無法設(shè)置需要注入的對象為 final,也無法注入那些不可變對象,final類型的變量在調(diào)用class的構(gòu)造函數(shù)的這個過程當中就得初始化完成,這個是基于字段的依賴注入做不到的地方,只能使用基于構(gòu)造函數(shù)的依賴注入的方式.
問題三、
字段注入的第三個問題是可能導(dǎo)致潛在的循環(huán)依賴,即兩個類之間互相進行注入,例如下面這段示例代碼:
public class ClassA { @Autowired private ClassB classB; } public class ClassB { @Autowired private ClassA classA; }
這里的 ClassA 和 ClassB 發(fā)生了循環(huán)依賴。上述代碼在 Spring 中是合法的,容器啟動時并不會報任何錯誤,而只有在使用到具體某個 ClassA 或 ClassB 時才會報錯。
問題四、
無法對注入的屬性進行安全檢查 在程序啟動的時候無法拿到這個類,只有在真正的業(yè)務(wù)使用的時候才會拿到,若注入的是null,因為不調(diào)用將一直無法發(fā)NullPointException的存在。 或者想在屬性注入的時候,增加驗證措施,也無法辦到。
基于以上四點,無論是 IDEA,還是 Spring 官方,都不推薦開發(fā)人員使用字段注入這種注入模式,而是推薦構(gòu)造器注入。
在面試中,針對字段注入,請記住它主要的三點缺陷:不具備外部可見性、會導(dǎo)致循環(huán)依賴,以及無法注入不可變對象。
構(gòu)造器注入
@Controller @RequestMapping("employee") public class EmployeeController { private final EmployeeMapper employeeMapper; @Autowired public EmployeeController(EmployeeMapper employeeMapper) { this.employeeMapper = employeeMapper; } }
優(yōu)點:
- 保證依賴不可變(final關(guān)鍵字)。
- 保證依賴不為空(省去了我們對其檢查)。
- 保證返回客戶端(調(diào)用)的代碼的時候是完全初始化的狀態(tài)。
- 避免了循環(huán)依賴。
- 提升了代碼的可復(fù)用性。
- 可以明確成員變量的注入順序。
缺點:
- 當注入?yún)?shù)較多時,代碼臃腫。
set方法注入
@Controller @RequestMapping("employee") public class EmployeeController { private EmployeeMapper employeeMapper; @Autowired public void setEmployeeMapper(EmployeeMapper employeeMapper) { this.employeeMapper = employeeMapper; } }
優(yōu)點:
- 相比構(gòu)造器注入,set注入類似于選擇性注入。
- 允許在類構(gòu)造完成后重新注入。
缺點: 暫無
到此這篇關(guān)于Spring依賴注入DI之三種依賴注入類型詳解的文章就介紹到這了,更多相關(guān)Spring依賴注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中excel表數(shù)據(jù)的批量導(dǎo)入方法
這篇文章主要為大家詳細介紹了Java中excel表數(shù)據(jù)的批量導(dǎo)入方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05springboot配置內(nèi)存數(shù)據(jù)庫H2教程詳解
這篇文章主要介紹了springboot配置內(nèi)存數(shù)據(jù)庫H2的詳細教程,需要的朋友可以參考下2017-07-07Java數(shù)據(jù)結(jié)構(gòu)之鏈表實現(xiàn)(單向、雙向鏈表及鏈表反轉(zhuǎn))
這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之鏈表實現(xiàn)的相關(guān)資料,其中包括單向鏈表、雙向鏈表及鏈表反轉(zhuǎn)的實現(xiàn)代碼,需要的朋友可以參考下2021-06-06