Spring -- 依賴注入(控制反轉)
依賴注入
Spring框架的核心功能有兩個:
Spring容器作為超級大工廠,負責建立、管理所有的Java物件,這些Java物件被稱為Bean。
Spring容器管理容器中Bean之間的依賴關係,Spring使用一種被稱為"依賴注入"的方式來管理Bean之間的依賴關係。
使用依賴注入,不僅可以為Bean注入普通的屬性值,還可以注入其他Bean的引用。依賴注入是一種優秀的解耦方式,
其可以讓Bean以配置檔案組織在一起,而不是以硬編碼的方式耦合在一起。
理解依賴注入
IoC(控制反轉)和DI(依賴注入)的意思是相同的,只是表述方式不一樣。
當某個Java物件(呼叫者)需要呼叫另一個Java物件(被依賴物件)的方法時,傳統模式下通常有兩種做法:
1.原始做法:呼叫者主動建立被依賴物件,然後再呼叫被依賴物件的方法。
就比如A類中要使用B類的方法,必須要先建立B類例項,再由B類例項呼叫B類的方法
2.簡單工廠模式:呼叫者先找到被依賴物件的工廠,然後主動通過工廠去獲取被依賴物件,最後再
呼叫被依賴物件的方法:
Phone p = PhoneFactory.getPhone();
p.callSomeOne(String phoneNum);
兩種方式獲取被依賴物件的方式都是主動的,這必然會導致呼叫者與被依賴物件之間的硬編碼耦合,
非常不利於專案的升級和維護。使用Spring框架之後,呼叫者無需主動獲取被依賴物件,呼叫者只需要
被動的接受Spring容器為呼叫者建立的依賴物件即可。
核心配置檔案中的定義:
最後Java程式碼中就不需要主動去建立依賴物件了,這個依賴的過程由Spring實現:
由此可以見,使用了Spring後,呼叫者獲取被依賴物件的方式由原來的主動獲取,變成了被動接受 ,
所以Spring的創始人稱之為控制反轉。
但是從Spring的角度來看,Spring容器負責將被依賴的物件賦值給呼叫者的成員變數,相當於為呼叫者
注入它依賴的例項,另一個說法:依賴注入就是由此得來的。
實現依賴注入的方式
Spring支援3中依賴注入的方式,屬性注入、構造器注入、工廠方法注入(使用較少)
1.屬性注入
屬性注入是指IoC容器通過成員變數的setter方法來注入bean的屬性值或者被依賴物件。這種注入方式簡單、
直觀,因而再Spring的依賴注入裡大量使用。屬性注入使用<property>元素,使用name屬性指定bean的屬性
名稱,value屬性指定屬性值
2.構造器注入
利用構造器來設定依賴關係的方式,被稱為構造注入。通俗來說,就是驅動Spring在底層以反射方式
執行帶指定引數的構造器,當執行帶引數的構造器時,就可利用構造器引數對成員變數進行初始化:
bean類:
構造器注入的傳參方式有三種:
1.按照索引匹配入參:
索引從0開始,表示構造器引數列表中的順序,這種方式的缺點也很明顯:
引數列表的順序如果調整了,配置檔案也需要跟著調整。
2.按型別匹配入參:
type的值是型別的全路徑,這裡constructor標籤的順序也表示引數列表的順序,
如果構造器中列表是這樣的:(String name , String sex , int age),那麼為name
賦值的constructor標籤應該放在第一位,sex第二,age第三。
3.根據屬性名入參:
這種方式是最穩的了,不多BB。
自動裝配
Spring IOC 容器可以自動裝配 Bean,需要做的僅僅是在 <bean> 的 autowire 屬性裡指定自動裝配的模式,它能夠將當前例項中所有的物件屬性全部進行填充。
byType是根據型別自動裝配,但要求是依賴Bean在容器中只能有一個例項。
若IoC容器中有多個與目標Bean型別一致的Bean,容器將無法判斷哪個Bean最適合該屬性,會報錯。
byName是根據名稱自動裝配,要求是依賴的Bean的名稱和屬性名設定的完全相同。
這個屬性名指的是Bean中定義的欄位名:
那麼在配置檔案中對應的依賴bean的id值,也得是a:
自動裝配的缺點:
1.在配置檔案裡設定autowire屬性進行自動裝配將會裝配Bean的所有屬性,如果只希望裝配個別屬性時,
autowire屬性就不夠靈活了。
2.autowire屬性要麼根據型別自動裝配,要麼根據名稱自動裝配,不能兩者兼有之。