Spring依賴(lài)注入DI之三種依賴(lài)注入類(lèi)型詳解
Spring依賴(lài)注入

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

