依賴注入(Dependency Injection)的意思就是對象經過構造器函數參數,工廠方法的參數,或者成員屬性,定義了對象的依賴對象;容器在建立該對象時會負責注入這些依賴。這個過程是控制反轉的,即不是由即將建立的對象來管理本身的依賴的發現和實例化,而是有Spring容器來實現。sql
在Spring中依賴注入有兩種形式,第一種就是基於構造函數的注入,即經過調用構造函數,傳入參數,也就是依賴來完成整個依賴注入流程;第二種就是基於setter方法的注入。架構
構造函數的參數的匹配,要避免歧義,如指定類型,指定參數的次序等。若是是按照參數名字匹配,則必須開啓debug模式進行編譯,不然參數名字是不保留的。若是不想開啓debug模式編譯,則可使用@ConstructorProperties註解。
setter方法注入是先調用沒有參數的默認構造函數構建對象,或者沒有參數的靜態工廠方法,實例化bean後,調用setter方法來將該對象注入。併發
經過使用依賴注入,可使代碼更簡潔,更好地實現對象之間解耦。另外,經過依賴注入管理的的對象是POJO類,能夠更好地進行測試。分佈式
最佳實踐是經過構造器方法注入主要依賴對象,經過setter方法注入可選的依賴對象。雖然能夠在setter方法上加上@Required註解來實現主要依賴對象注入,但通常仍是推薦使用構造器注入必須的依賴。函數
使用構造器注入,可使得應用的組件做爲不可變的對象,並且能夠保證注入依賴是非null的。另外,構造器注入返回的是一個完整的初始狀態的實例。可是,通常不推薦大量使用構造方法注入,若是出現這種狀況,則說明代碼須要重構。高併發
setter方法適合注入可選的依賴,這些依賴可能有默認值,並且在其餘位置使用這些依賴時務必要進行null值檢查。使用setter方法的一個好處是能夠修改或者從新配置,或者須要時再注入。如基於JMX MBean的管理。源碼分析
首先ApplicationContext會被建立和初始化,會加載包括描述全部bean的元數據。這些配置元數據能夠經過XML,Java代碼或者註解來指定。性能
對於每個bean,它的依賴表現形式是成員屬性,構造器參數,或者靜態工廠方法的參數。在bean真正建立時,Spring容器會提供這些依賴的對象。這些參數多是須要設置的默認值,也多是另一個bean的引用。學習
Spring容器會驗證每一個bean的配置信息。而且在bean真正建立時才設置設置屬性值或者參數值。
在Spring中,單例做用域的bean會提早初始化,在Spring容器建立時就進行了實例化。對於其餘的做用域的bean,則只在須要時才進行建立。之因此單例做用域的bean會被提早初始化,主要是爲了解決依賴檢查的問題,下文的循環依賴一節會詳細說明。測試
在Spring內部會構建一個建立bean的依賴圖,按照這依賴關係來建立Bean。
若是使用構造函數注入,則不能有循環依賴的狀況。如A構造器依賴B,同時B也構造器依賴A。Spring IoC容器會在運行時檢測到循環依賴,拋BeanCurrentlyInCreationException異常。一種解決辦法是經過setter方法來解決循環依賴的狀況。
Spring會在容器加載時檢測配置問題,如引用不存在或者循環依賴。Spring會在必要時才解析依賴,即儘量晚的來解析依賴關係。延遲解析依賴可能致使後期請求獲取對象時報錯,如拋出一個異常,如丟失指定對象或者屬性。這種配置的延遲的可見性致使的問題使得ApplicationContext的實現要求單例做用域的bean提早記性初始化。雖然會耗費內存和時間,由於並非按需建立這些單例做用域的bean,可是能夠在ApplicationContext建立時就能夠發現配置問題。
下文會介紹經過指定bean的能夠經過配置來覆蓋默認的行爲,使得單例做用域的bean也是延遲初始化。
若是沒有循環依賴存在,則在注入依賴對象時,這些依賴的對象就已經初始化完成了。即若是A依賴B,則在A初始化時,B已經初始化完成了。也就是說,Bean是在相關依賴設置完成,而且相關的生命週期方法調用完畢後,纔算是完成了初始化。
默認狀況下ApplicationContext是提早初始化單例做用域的bean,做爲ApplicationContext初始化的一部分。這樣能夠儘快的發現配置問題。能夠經過指定bean的lazy-init="true",讓bean在須要時才被初始化。
在Spring中能夠自動注入依賴,能夠減小指定屬性或者構造器參數,還能夠隨着配置對象的變化來更新注入的對象。
自動注入依賴的模式有:經過名稱注入,經過類型注入,和經過構造器注入。
本文總結了Spring中的依賴管理的基本原理和常見的問題,具體的依賴注入配置語法還須要參考Spring的官方文檔來進行。
本文的重點是你有沒有收穫與成長,其他的都不重要,但願讀者們能謹記這一點。同時我通過多年的收藏目前也算收集到了一套完整的學習資料,包括但不限於:分佈式架構、高可擴展、高性能、高併發、Jvm性能調優、Spring,MyBatis,Nginx源碼分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多個知識點高級進階乾貨,但願對想成爲架構師的朋友有必定的參考和幫助