Spring——依賴注入(DI)詳解
宣告:本部落格僅僅是一個初學者的學習記錄、心得總結,其中肯定有許多錯誤,不具有參考價值,歡迎大佬指正,謝謝!想和我交流、一起學習、一起進步的朋友可以加我微信Liu__66666666
這是簡單學習一遍之後的記錄,後期還會修改。
一、概念引入
我們通過前文Spring——IOC已經知道怎麼建立一個空白的例項物件,但是這個例項物件是沒有進行任何成員變數設定的,都是預設值,例如int型別預設為0、引用型別預設為null。
那我們如果想建立帶有特定屬性的物件,那現在有個Computer類,他有屬性”型號“。所以出廠的時候這個屬性就是早被設定好了,那程式碼中的工廠如何去設定這個屬性呢?其實依賴注入(DI,Dependency Injection)所做的工作就是為Spring中的Bean設定屬性(成員變數的值)。
百度百科概念:所謂依賴注入,是指程式執行過程中,如果需要呼叫另一個物件協助時,無須在程式碼中建立被呼叫者,而是依賴於外部的注入。Spring的依賴注入對呼叫者和被呼叫者幾乎沒有任何要求,完全支援對POJO之間依賴關係的管理。
二、依賴注入方式
依賴注入常見的有三種:
- 通過構造方法注入
- setter方法注入
- 介面注入
現在有蘋果電腦公司的“MacBook pro 2019”型號的電腦都是“macOS Mojave”系統,那該怎麼設定型號和作業系統這兩個屬性呢?下面我們就以這個電腦為例探討一下!
首先建好專案並匯入jar包,建立好applicationContext.xml檔案,操作步驟參考Spring——IOC
專案目錄結構如下:
Computer類:
public class Computer { private String type;//電腦型號 private OperatingSystem operatingSystem;//作業系統 public Computer() {} public Computer(String type, OperatingSystem operatingSystem) { this.type = type; this.operatingSystem = operatingSystem; } //此處略去getter setter toString方法 }
OperatingSystem類(這是Computer的一個屬性:作業系統)
public class OperatingSystem {
private String name;//作業系統名字,例如Windows、macOS
//作業系統版本,例如,當name為Windows,version為10的時候,就是win10
private String version;
public OperatingSystem(){}
public OperatingSystem(String name, String version) {
this.name = name;
this.version = version;
}
//此處略去getter setter toString方法
}
1.構造方法注入(一定要寫對應的構造方法!)
此方式使用的是bean標籤內部的
以如下構造方法為例
public Computer(String type, OperatingSystem operatingSystem) {
this.type = type;
this.operatingSystem = operatingSystem;
}
- 寫法1(不推薦,不常用):
<!--macOS mojave-->
<bean id="operatingSystem" class="di.OperatingSystem">
<constructor-arg index="0" value="macOS"/>
<constructor-arg index="1" value="Mojave"/>
</bean>
<bean id="computer" class="di.Computer">
<constructor-arg index="0" value="MacBook Pro 2019"/>
<constructor-arg index="1" ref="operatingSystem"/>
</bean>
每個constructor-arg標籤代表構造方法中的一個引數;
屬性index代表引數的順序,從0開始,index=“0”代表的是構造方法的String type這個引數,index=“1”代表的是OperatingSystem這個引數;
屬性value代表的是這個引數要傳入的值,例如type這個引數對應的是macOS,version是Mojave,一般來說,基本型別和String型別要用value屬性來傳值。
由於在Computer類中我們引用了OperatingSystem這個物件,所以需要先定義好OperatingSystem這個bean,以供我們將其注入到computer這個bean中,其實OperatingSystem就是Computer的一個依賴。而在第二個bean中,有一個ref屬性,這個用來傳value傳不了的值,ref在本例中的值為operatingSystem這個bean的id。
- 寫法2(推薦寫法,但不常用):
<!--macOS mojave-->
<bean id="operatingSystem" class="di.OperatingSystem">
<constructor-arg name="name" value="macOS"/>
<constructor-arg name="version" value="Mojave"/>
</bean>
<bean id="computer" class="di.Computer">
<constructor-arg name="type" value="MacBook Pro 2019"/>
<constructor-arg name="operatingSystem" ref="operatingSystem"/>
</bean>
其他地方與寫法1一樣,唯一區別就是將寫法1中的index屬性換成了name屬性,這樣直接通過引數名來確定,清晰明瞭,不容易出錯。
2.setter方法注入(一定要寫好空參構造和所有屬性的setter方法!!!)
此方式使用的是bean標籤內部的
以如下構造方法為例
public Computer(String type, OperatingSystem operatingSystem) {
this.type = type;
this.operatingSystem = operatingSystem;
}
注入:
<!--macOS mojave-->
<bean id="operatingSystem" class="di.OperatingSystem">
<property name="name" value="macOS"/>
<property name="version" value="Mojave"/>
</bean>
<bean id="computer" class="di.Computer">
<property name="type" value="MacBook Pro 2019"/>
<property name="operatingSystem" ref="operatingSystem"/>
</bean>
其實與建構函式注入的第二種方式差不多,只不過是把
3.介面注入(沒用,不說了)
三、集合注入
注意:下文中的value標籤,當需要設的值是自己定義的bean時,要用
為Computer類新增屬性keys,表示鍵盤上的鍵的集合。
1.陣列與List(可互相替換)
其實Spring中將Array和List等同起來了。
寫法1(constructor-arg + array):
<bean id="computer" class="di.Computer">
<constructor-arg name="keys">
<array>
<value>a</value>
<value>b</value>
<value>c</value>
</array>
</constructor-arg>
</bean>
寫法2(constructor-arg + list):
<bean id="computer" class="di.Computer">
<constructor-arg name="keys">
<list>
<value>a</value>
<value>b</value>
</list>
</constructor-arg>
</bean>
寫法3(property + array):
<bean id="computer" class="di.Computer">
<property name="keys">
<array>
<value>a</value>
<value>b</value>
</array>
</property>
</bean>
寫法4(property + list):
<bean id="computer" class="di.Computer">
<property name="keys">
<list>
<value>a</value>
<value>b</value>
</list>
</property>
</bean>
2.Set
寫法1(constructor-arg):
<bean id="computer" class="di.Computer">
<constructor-arg name="keys">
<set>
<value>a</value>
<value>b</value>
</set>
</constructor-arg>
</bean>
寫法2(property):
<bean id="computer" class="di.Computer">
<property name="keys">
<set>
<value>a</value>
<value>b</value>
</set>
</property>
</bean>
3.Map
為Computer類新增屬性map<String,String> sofewares,key表示軟體,value表示軟體安裝目錄
為Computer類新增屬性map<String,Singer> songs,key表示歌曲名,value表示歌手物件
寫法1(property):
<bean id="singerEdSheeran" class="di.Singer">
<property name="name" value="Ed Sheeran"/>
</bean>
<bean id="computer" class="di.Computer">
<property name="softwares">
<map>
<entry key="WeChat" value="/Users/...."/>
<entry key="Intellij Idea" value="/usr/local/...."/>
</map>
</property>
<property name="songs">
<map>
<entry key="Shape of You" value-ref="singerEdSheeran"/>
<entry key="I dont care" value-ref="singerEdSheeran"/>
</map>
</property>
</bean>
寫法2(將寫法1的property換成constructor-arg即可)
注意,如果key或value要引用其他bean,那麼對應地需要將