一
公司小伙伴使用了構造器注入,說是spring的官方推薦。但是,我問了三個問題,他都答不出來,感覺能寫篇博文。
官方為什么推薦構造器注入?
構造器注入和屬性注入的區別是啥?
你知道有幾種注入方式嗎?
可以看出當時我問題是由深入淺的,因為這哥們答不上,我只能降低難度了。問完發現然並卵,只是個糾結於規范的人。
那我就從后往前答。
二 注入方式
spring的注入方式就兩種 配置注入,注解注入(自動裝配)
源碼里的beanfactory和xmlbeanfactory
而這兩種方式都實現了三種注入方法,訪問器注入(setterXXX,newXXX,initXXX等),屬性注入(filed),構造器注入(constructor)。
里面花樣比較多的是訪問器注入,看網上還有靜態方法注入,靜態工廠注入,初始化注入,本質上就是在一個方法里面注入...
下圖為注解注入的三種注入使用簡易圖。注意僅說明格式,該類使用是錯誤的,只需一種即可
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找機會.求大佬推薦啊
