Spring的構(gòu)造器注入全過(guò)程
一、前言
Spring框架對(duì)Java開(kāi)發(fā)的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反轉(zhuǎn))和AOP,平時(shí)使用最多的就是其中的IOC,我們通過(guò)將組件交由Spring的IOC容器管理,將對(duì)象的依賴(lài)關(guān)系由Spring控制,避免硬編碼所造成的過(guò)度程序耦合。
前幾天的時(shí)候,筆者的同事問(wèn)我為什么要使用構(gòu)造器的注入方式,我回答說(shuō)因?yàn)镾pring文檔推薦這種,而說(shuō)不出為什么 T^T,后面抽時(shí)間了解了一下,下面就是筆者要討論的就是其注入方式。
二、常見(jiàn)的三種注入方式
1.注解注入
筆者為了方便起見(jiàn)就只是用注解的方式注入(現(xiàn)在也很少使用xml了吧)
Controller
public class FooController {
@Autowired
//@Inject
private FooService fooService;
//簡(jiǎn)單的使用例子,下同
public List<Foo> listFoo() {
return fooService.list();
}
}這種注入方式應(yīng)該是筆者目前為止開(kāi)發(fā)中見(jiàn)到的最常見(jiàn)的注入方式。原因很簡(jiǎn)單:
注入方式非常簡(jiǎn)單:加入要注入的字段,附上@Autowired,即可完成。使得整體代碼簡(jiǎn)潔明了,看起來(lái)美觀大方。
2.構(gòu)造器注入
Controller
public class FooController {
private final FooService fooService;
@Autowired
public FooController(FooService fooService) {
this.fooService = fooService;
}
//使用方式上同,略
}在Spring4.x版本中推薦的注入方式就是這種,相較于上面的field注入方式而言,就顯得有點(diǎn)難看,特別是當(dāng)注入的依賴(lài)很多(5個(gè)以上)的時(shí)候,就會(huì)明顯的發(fā)現(xiàn)代碼顯得很臃腫。
對(duì)于從field注入轉(zhuǎn)過(guò)來(lái)+有強(qiáng)迫癥的園友 來(lái)說(shuō),簡(jiǎn)直可以說(shuō)是石樂(lè)志 (`Д´*)9。對(duì)于這一點(diǎn)我們后面再來(lái)討論,別急。
3.setter注入
@Controller
public class FooController {
private FooService fooService;
//使用方式上同,略
@Autowired
public void setFooService(FooService fooService) {
this.fooService = fooService;
}
}在Spring3.x剛推出的時(shí)候,推薦使用注入的就是這種,筆者現(xiàn)在也基本沒(méi)看到過(guò)這種注解方式,寫(xiě)起來(lái)麻煩,當(dāng)初推薦Spring自然也有他的道理,這里我們引用一下Spring當(dāng)時(shí)的原話:
The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.
Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.
簡(jiǎn)單的翻譯一下就是:構(gòu)造器注入?yún)?shù)太多了,顯得很笨重,另外setter的方式能用讓類(lèi)在之后重新配置或者重新注入。
那么后面為什么又換成構(gòu)造器注入了呢?(喂喂喂,Spring你前一大版本還貶低構(gòu)造器注入,后面就立刻捧人家了不好吧,不過(guò)能用于承認(rèn)自己的錯(cuò)誤,才是真正令人稱(chēng)贊的地方吧 (?•??•?)??)
三、構(gòu)造器注入的好處
Spring官方寫(xiě)的這個(gè)構(gòu)造器注入可以保證注入的組件不可變,因?yàn)榻M件是用final修飾的,另外可以保證組件不為空。此外返回給客戶(hù)端的時(shí)候保證組件是完整初始化后的狀態(tài)。
下面來(lái)簡(jiǎn)單的解釋一下:
1、依賴(lài)不可變:其實(shí)說(shuō)的就是final關(guān)鍵字,這里不再多解釋了。不明白的園友可以回去看看Java語(yǔ)法。
2、依賴(lài)不為空(省去了我們對(duì)其檢查):當(dāng)要實(shí)例化FooController的時(shí)候,由于自己實(shí)現(xiàn)了有參數(shù)的構(gòu)造函數(shù),所以不會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù),那么就需要Spring容器傳入所需要的參數(shù),所以就兩種情況:1、有該類(lèi)型的參數(shù)->傳入,OK 。2:無(wú)該類(lèi)型的參數(shù)->報(bào)錯(cuò)。所以保證不會(huì)為空,Spring總不至于傳一個(gè)null進(jìn)去吧
3、完全初始化的狀態(tài):這個(gè)可以跟上面的依賴(lài)不為空結(jié)合起來(lái),向構(gòu)造器傳參之前,要確保注入的內(nèi)容不為空,那么肯定要調(diào)用依賴(lài)組件的構(gòu)造方法完成實(shí)例化。而在Java類(lèi)加載實(shí)例化的過(guò)程中,構(gòu)造方法是最后一步(之前如果有父類(lèi)先初始化父類(lèi),然后自己的成員變量,最后才是構(gòu)造方法,這里不詳細(xì)展開(kāi)。)。所以返回來(lái)的都是初始化之后的狀態(tài)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合freemarker實(shí)現(xiàn)代碼生成器
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何整合freemarker實(shí)現(xiàn)一個(gè)簡(jiǎn)單的代碼生成器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-03-03
Java Druid連接池與Apache的DBUtils使用教程
這篇文章主要介紹了Java Druid連接池與Apache的DBUtils使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-12-12
Java實(shí)現(xiàn)分布式鎖的3種方法總結(jié)
分布式鎖是一種用于保證分布式系統(tǒng)中多個(gè)進(jìn)程或線程同步訪問(wèn)共享資源的技術(shù),同時(shí)它又是面試中的常見(jiàn)問(wèn)題,所以我們本文就重點(diǎn)來(lái)看分布式鎖的具體實(shí)現(xiàn),希望對(duì)大家有所幫助2023-09-09
Spring Boot插件spring tool suite安裝及使用詳解
這篇文章主要介紹了Spring Boot插件spring tool suite安裝及使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Mybatis-Plus中的MetaObjectHandler組件的使用
MetaObjectHandler是Mybatis-Plus中一個(gè)實(shí)用組件,專(zhuān)門(mén)用于自動(dòng)處理實(shí)體對(duì)象中的特定字段,如創(chuàng)建時(shí)間、更新時(shí)間、創(chuàng)建人和修改人等,該接口允許開(kāi)發(fā)者在不修改業(yè)務(wù)代碼的情況下,實(shí)現(xiàn)自動(dòng)填充功能,極大地簡(jiǎn)化了代碼的復(fù)雜性,感興趣的可以了解一下2024-10-10

