在學習的第一天就跟着demo練習了一番spring依賴注入的
具體操作,在接下來的幾天對於爲什麼要這麼做有了一定的認識,今天對於依賴注入的具體方式來進行一下細分。
一、構造函數注入
通過構造函數來進行依賴關係的設定,默認是使用的無參構造,如果重寫了構造函數改成帶參數的而沒有無參構造,直接使用如下注入會失敗。
String name;
Integer price;
Date byDate;
public Car(String name, Integer price, Date byDate) {
this.name = name;
this.price = price;
this.byDate = byDate;
}
<bean name="car" class="com.pojo.Car" ></bean>
運行後錯誤提示
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.pojo.Car]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.pojo.Car.<init>()
配置
這個時候如果要使用構造器注入對應的屬性應該使用標籤constructor-arg來注入有參構造的參數。
其中的屬性如下:
type:通過指定要注入數據的數據類型,該數據類型也是構造函數中某個參數的類型(同參數類型的參數會引起混亂)
index:用於指定要注入數據給構造函數中指定索引位置的參數賦值,索引位置是從0開始。
name:用於指定給構造函數中指定名稱的參數賦值(常用)
賦值類型:
value:基本類型和String類型賦值
ref:用於指定其他的bean類型數據(交給spring管理的bean對象)
代碼示例
<bean name="car" class="com.pojo.Car" >
<constructor-arg name="name" value="雷克薩斯"></constructor-arg>
<constructor-arg name="price" value="600000"></constructor-arg>
<constructor-arg name="byDate" value="2018-1-1"></constructor-arg>
</bean>
此處Integer類型直接使用value可以將寫入的值進行轉換,但是Date類型並不會進行轉換。
提示如下:
Could not convert argument value of type [java.lang.String] to required type [java.util.Date]: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'
正確的寫法應該先配置一個日期對象然後使用ref引用改對象對其進行賦值。
<bean name="car" class="com.pojo.Car" >
<constructor-arg name="name" value="雷克薩斯"></constructor-arg>
<constructor-arg name="price" value="600000"></constructor-arg>
<constructor-arg name="byDate" ref="newDate"></constructor-arg>
</bean>
<bean name="newDate" class="java.util.Date"></bean>
總結:
優勢:獲取對象時,注入必須的操作否則對象沒法創建成功。
弊端:改變了bean對象的實例化方式,如果創建對象用不到的數據,但是也必須提供。
方法注入(常用)
配置
標籤:property
位置:bean標籤內部
屬性:
name:用於指定注入時所調用的set方法名稱(注意是set方法名稱,與變量名無關)
value:用於提供基本類型和String類型的數據
ref:用於指定其他的bean類型數據。(交給spring管理的bean對象)
代碼示例
public class Car {
String name;
Integer price;
Date byDate;
public void setName(String name) {
this.name = name;
}
public void setPrice(Integer price) {
this.price = price;
}
public void setByDate(Date byDate) {
this.byDate = byDate;
}
}
調用set方法,使用默認無參構造函數。
<bean name="car" class="com.pojo.Car" >
<property name="name" value="梅賽德斯"/>
<property name="byDate" ref="newDate"/>
<property name="price" value="1000000"/>
</bean>
總結
優勢:創建對象時沒有明確限制,可以直接使用默認的構造函數
弊端:如果某個成員必須有值,獲取對象時有可能set方法還沒有執行。
複合類型注入
對於參數是集合類型的注入方法
配置
標籤:還是使用的set注入的標籤property
位置:bean標籤內部
代碼示例
public class Car {
String[] strs;
List list;
Map map;
Set set;
public void setList(List list) {
this.list = list;
}
public void setMap(Map map) {
this.map = map;
}
public void setStrs(String[] strs) {
this.strs = strs;
}
}
public void setSet(Set set) {
this.set = set;
}
<bean name="car" class="com.pojo.Car" >
<property name="list">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="set">
<set>
<value>111</value>
<value>222</value>
</set>
</property>
<property name="strs">
<array>
<value>111</value>
<value>222</value>
</array>
</property>
<property name="map">
<map>
<entry key="no1" value="abc"></entry>
<entry key="no2" value="qwe"></entry>
<entry key="no3" value="zxc"></entry>
</map>
</property>
但是在使用時發現關於list 、set 、數組類型的時候因爲數據結構類型的類似,標籤使用同一個也是可以注入的。
例:
<bean name="car" class="com.pojo.Car" >
<property name="list">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="set">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="strs">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="map">
<map>
<entry key="no1" value="abc"></entry>
<entry key="no2" value="qwe"></entry>
<entry key="no3" value="zxc"></entry>
</map>
</property>
總結:
關於集合類型的注入其實就分爲兩種一種是list(也可以使用set、array)、一種是map、props的鍵值類型,類型相同標籤可以互換。