spring 依賴注入總結--爲何官方推薦構造器注入

公司小夥伴使用了構造器注入,說是spring的官方推薦。可是,我問了三個問題,他都答不出來,感受能寫篇博文。java

 

官方爲何推薦構造器注入?spring

構造器注入和屬性注入的區別是啥?安全

你知道有幾種注入方式嗎?框架

 

能夠看出當時我問題是由深刻淺的,由於這哥們答不上,我只能下降難度了。問完發現然並卵,只是個糾結於規範的人。jvm

那我就從後往前答。spring-boot

 

二  注入方式

spring的注入方式就兩種 配置注入,註解注入(自動裝配)性能

源碼裏的beanfactory和xmlbeanfactory

 

而這兩種方式都實現了三種注入方法,訪問器注入(setterXXX,newXXX,initXXX等),屬性注入(filed),構造器注入(constructor)。優化

裏面花樣比較多的是訪問器注入,看網上還有靜態方法注入,靜態工廠注入,初始化注入,本質上就是在一個方法裏面注入...ui

 

下圖爲註解注入的三種注入使用簡易圖。注意僅說明格式,該類使用是錯誤的,只需一種便可spa

ps.能夠看出這三個注入,訪問器和構造器都是一個方法,咱們是否是能夠是有兩種注入?屬性注入和方法注入?

那爲何我說三種,實際上是基於配置注入區分的。(在本身的類注入,在本身的類注入其餘類實例,在本身的類注入 其餘類經過訪問器生成的實例,沒記錯應該是這三個求打臉)

 

可是基於java8支持多註解,spring出了spring-boot,從而把配置丟掉的人不在小數

是的就是我。雖然配置化的項目泛用性強,可是配置一多,重複率比代碼還高,因此盲目的追求項目的配置化並很差,spring就把這部分精簡到代碼裏面了

 

三 注入方法的區別

經過優缺點的對比,相信你們能更加清楚的明白,爲何分三種

 

1.屬性注入

優勢:注入簡單。簡潔明瞭。(寫了這麼久代碼,我發現簡潔明瞭纔是最重要的,語法糖都是異端)

缺點:循環依賴。重名依賴。依賴爲空。被多方依賴的可能經過反射修改了內部的值。

 

2.構造器注入

優勢:初始化。不可變性。數據檢查,依賴不爲空。

缺點:循環依賴。注入的一多就很是的臃腫。

 

3.訪問器注入

優勢:經過調用,可讓代碼控制類依賴的順序,解決循環依賴

缺點:注入的一多就很是的臃腫。

 

先反駁一下循環依賴,@Lazy標籤瞭解下,因此第一個被排除的是訪問器注入。而構造器注入和屬性注入的循環依賴的報錯提示也有點不一樣,前者編譯時就報錯,後者使用時報錯

再說下重名依賴,@Qualifier標籤瞭解下。

同理依賴爲空,你寫的代碼爲何npe還好意思說是框架的缺點?這三個都是能夠經過我的的代碼技術解決的因此就放在一塊兒了。

 

被多方依賴的可能經過反射修改了內部的值,也就是構造器注入的初始化和不可變性,該方法確實在多人協同寫代碼(調用同一個service時)有很大的幫助

 

因此簡化下我上面說的優缺點,就變成這樣

 

    屬性注入                                構造器注入                    訪問器注入

優勢  簡單,可讀性高        數據檢查;不可變性,多人協同安全  時代的眼淚

缺點  內部屬性可變,多人協同出問題 注入多個就臃腫      

 

四 爲何官方推薦構造器注入 ?

說到底,不可變性,多人協同代碼安全,只是菜雞的自我安慰。國外頂級項目的開發團隊,可能還不如我國一個外包項目組的人多。

代碼寫多了,當你發現周圍的總是頻繁的改動數據,線程不安全等,最簡單的方法是換隊友或者單幹,由於你的一點點遷就,只會發現他有更多更大的問題。

 

官方着重的是數據檢查,非空檢查,循環依賴檢查,重名檢查等,正如前面說的

構造器注入和屬性注入的循環依賴的報錯提示也有點不一樣,前者編譯時就報錯,後者使用時報錯

儘可能把錯誤在編譯時就發現纔是最好好的開發習慣!機器的可信度遠高於人類!(爲何我寫這篇文章的緣由就是在於此,網上不少相關文章,可是都沒有答到點子上)

推薦構造器注入的理由就是這麼簡單

 

ps.有興趣的看下這文章

spring官網文章

訪問器注入vs構造器注入和required的使用 https://spring.io/blog/2007/07/11/setter-injection-versus-constructor-injection-and-the-use-of-required/

 

五 非spring下的屬性,構造器和訪問器建立對象的對比

這裏說的和本篇文章無關,只是興趣使然,寫一寫代碼優化的思路。

 

屬性是類加載建立對象,構造器是類初始化建立對象,訪問器是建立指定對象。

訪問器顯然是需求指定的實現,不在討論範圍以內。那麼屬性和構造器呢?

 

顯然加載了不使用,只是在浪費jvm的資源。因此使用構造器建立對象,性能更好。

 

ps.爲何這個和spring無關?

spring的基礎ioc知道吧?全部的spring bean本質上咱們都是反射調用,因此不管是構造器仍是屬性,對象早已被初始化到spring容器之了

 

ps.ps 深圳java找機會.求大佬推薦啊

相關文章
相關標籤/搜索