公司小夥伴使用了構造器注入,說是spring的官方推薦。可是,我問了三個問題,他都答不出來,感受能寫篇博文。java
官方爲何推薦構造器注入?spring
構造器注入和屬性注入的區別是啥?安全
你知道有幾種注入方式嗎?框架
能夠看出當時我問題是由深刻淺的,由於這哥們答不上,我只能下降難度了。問完發現然並卵,只是個糾結於規範的人。jvm
那我就從後往前答。spring-boot
spring的注入方式就兩種 配置注入,註解注入(自動裝配)性能
源碼裏的beanfactory和xmlbeanfactory
而這兩種方式都實現了三種注入方法,訪問器注入(setterXXX,newXXX,initXXX等),屬性注入(filed),構造器注入(constructor)。優化
裏面花樣比較多的是訪問器注入,看網上還有靜態方法注入,靜態工廠注入,初始化注入,本質上就是在一個方法裏面注入...ui
下圖爲註解注入的三種注入使用簡易圖。注意僅說明格式,該類使用是錯誤的,只需一種便可spa
ps.能夠看出這三個注入,訪問器和構造器都是一個方法,咱們是否是能夠是有兩種注入?屬性注入和方法注入?
那爲何我說三種,實際上是基於配置注入區分的。(在本身的類注入,在本身的類注入其餘類實例,在本身的類注入 其餘類經過訪問器生成的實例,沒記錯應該是這三個求打臉)
可是基於java8支持多註解,spring出了spring-boot,從而把配置丟掉的人不在小數
是的就是我。雖然配置化的項目泛用性強,可是配置一多,重複率比代碼還高,因此盲目的追求項目的配置化並很差,spring就把這部分精簡到代碼裏面了
經過優缺點的對比,相信你們能更加清楚的明白,爲何分三種
優勢:注入簡單。簡潔明瞭。(寫了這麼久代碼,我發現簡潔明瞭纔是最重要的,語法糖都是異端)
缺點:循環依賴。重名依賴。依賴爲空。被多方依賴的可能經過反射修改了內部的值。
優勢:初始化。不可變性。數據檢查,依賴不爲空。
缺點:循環依賴。注入的一多就很是的臃腫。
優勢:經過調用,可讓代碼控制類依賴的順序,解決循環依賴
缺點:注入的一多就很是的臃腫。
先反駁一下循環依賴,@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/
這裏說的和本篇文章無關,只是興趣使然,寫一寫代碼優化的思路。
屬性是類加載建立對象,構造器是類初始化建立對象,訪問器是建立指定對象。
訪問器顯然是需求指定的實現,不在討論範圍以內。那麼屬性和構造器呢?
顯然加載了不使用,只是在浪費jvm的資源。因此使用構造器建立對象,性能更好。
ps.爲何這個和spring無關?
spring的基礎ioc知道吧?全部的spring bean本質上咱們都是反射調用,因此不管是構造器仍是屬性,對象早已被初始化到spring容器之了。
ps.ps 深圳java找機會.求大佬推薦啊