Spring 中的依賴注入
依賴注入:Dependency Injection,它是 spring 框架核心 ioc 的具體實現
我們的程序在編寫時,通過控制反轉,把對象的創建交給了 spring,但是代碼中不可能出現沒有依賴的情況,ioc 解耦只是降低他們的依賴關係,但不會消除
例如:我們的業務層仍會調用持久層的方法,那這種業務層和持久層的依賴關係,在使用 spring 之後,就讓 spring 來維護了,簡單的說,就是坐等框架把持久層對象傳入業務層,而不用我們自己去獲取
通過構造函數實現依賴注入
顧名思義,就是使用類中的構造函數,給成員變量賦值,賦值的操作不是我們自己做的,而是通過配置的方式,讓 Spring 框架來爲我們注入的,下面我們來看具體代碼:
AccountServiceImpl 類中存在着String
、Integer
、Date
三種類型的變量。分別代表基本類型及 String
、其他特殊類型
兩大類,並提供他們的構造函數:
package com.lmh.service.impl;
import com.lmh.dao.IAccountDao;
import com.lmh.dao.impl.AccountDaoImpl;
import com.lmh.service.IAccountService;
import java.util.Date;
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println("save service");
System.out.println(name + ", " + age + ", " + birthday);
}
}
在bean.xml
中配置依賴注入:
<bean id="now" class="java.util.Date"/>
<bean id="accountService" class="com.lmh.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="test"/>
<constructor-arg name="age" value="18"/>
<constructor-arg name="birthday" ref="now"/>
</bean>
這裏需要注意,由於Date
是其他特殊類型,不被包含在 Java 的基本類型或字符串中,所以我們需要爲Date
類型創建一個<bean>
,然後在另一個<bean>
的<constructor-arg>
標籤中使用ref
屬性來引用它,實現依賴注入
這裏我是使用<constructor-arg>
標籤的name
屬性來指定變量名實現依賴注入的,<constructor-arg>
標籤還支持使用type
和index
兩個屬性,其中type
是根據變量類型爲變量賦值,這裏存在使用的侷限性,index
通過變量在構造函數參數列表中的位置(從 0 開始)來爲變量賦值,可以看到,使用name
還是比較實用的
而value
標籤是爲基本類型變量直接賦值,它可以將" "
中的值自動轉換爲相應的數據類型,ref
是專門爲特殊的類型進行賦值的,它通過引用定義好的<bean>
來進行賦值
優缺點
優勢:在獲取 bean 對象時,注入數據是必須的操作,否則對象無法創建成功
弊端:改變了 bean 對象的實例化方式,在我們創建對象時,如果用不到這些數據,也必須提供
通過 Set 方法實現依賴注入
該方法我們需要在類中爲變量添加對應的 set 方法:
package com.lmh.service.impl;
import com.lmh.service.IAccountService;
import java.util.Date;
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl2 implements IAccountService {
// 如果是經常變化的數據,並不適用於注入的方式
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println("save service");
System.out.println(name + ", " + age + ", " + birthday);
}
}
在bean.xml
中配置依賴注入:
<bean id="accountService2" class="com.lmh.service.impl.AccountServiceImpl2">
<property name="name" value="test"/>
<property name="age" value="21"/>
<property name="birthday" ref="now"/>
</bean>
使用 set 方法實現依賴注入時,我們使用<bean>
標籤內部的<property>
標籤,<property>
標籤的使用以及內部的屬性和<constructor-arg>
標籤相同,對於Date
這種類型,同樣需要使用引用的方式進行賦值
優缺點
優勢:創建對象時沒有明確的限制,可以直接使用默認構造函數
弊端:如果有某個成員必須有值,則獲取對象時有可能 set 方法沒有執行
集合類型變量的依賴注入
集合類型的變量如何實現依賴注入呢?我們這裏以 set 方法爲例
package com.lmh.service.impl;
import com.lmh.service.IAccountService;
import java.util.*;
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl3 implements IAccountService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, String> myMap;
private Properties myProps;
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
@Override
public void saveAccount() {
System.out.println("save service");
System.out.println(Arrays.toString(myStrs));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
System.out.println(myProps);
}
}
在bean.xml
中配置依賴注入:
<bean id="accountService3" class="com.lmh.service.impl.AccountServiceImpl3">
<property name="myStrs">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
<value>DDD</value>
</array>
</property>
<property name="myList">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
<value>DDD</value>
</list>
</property>
<property name="mySet">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
<value>AAA</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="testA" value="aaa"/>
<entry key="testB" value="bbb"/>
</map>
</property>
<property name="myProps">
<props>
<prop key="testc">ccc</prop>
<prop key="testd">ddd</prop>
</props>
</property>
</bean>
以上是集合類型變量使用 set 方法實現依賴注入的代碼,這裏需要注意一點,相同類型的集合可以使用相同的標籤實現依賴注入,即array、List、Set
屬於同類型,Map、Properties
屬於同類型,例如array
可以通過<list>
標籤實現依賴注入