在Spring入門這一章中,驗證了通過IoC創建對象,沒有調用業務層的保存用戶的方法,當你調用業務層方法時,會出現如下錯誤:
很明顯,雖然我們通過控制反轉獲得到持久層和業務層的對象,但是對象之間並沒有什麼任何關係,因此纔會出現空指針異常的錯誤。怎麼把持久層對象傳入業務層呢???這就需要 依賴注入(Dependency Injection) 了。
依賴注入方式一 : 構造函數注入
使用構造函數的方式,給屬性賦值。
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl implements AccountService {
private String name;
private Double money;
private Date birthday;
public AccountServiceImpl(String name,Date birthday,Double money)
{
this.name = name;
this.money = money;
this.birthday = birthday;
}
public void saveAccount() {
System.out.println("賬戶信息爲 姓名:"+name+" 生日:"+birthday+" 餘額:"+money);
}
}
通過配置方式給有參構造函數的屬性賦值
<bean id="accountService" class="com.liang.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="張三"></constructor-arg>
<constructor-arg name="birthday" ref="birthday"></constructor-arg>
<constructor-arg name="money" value="100.0"></constructor-arg>
</bean>
<bean id="birthday" class="java.util.Date"></bean>
constructor-org標籤屬性說明
屬性 | 功能 |
---|---|
index | 參數在構造函數參數列表的索引位置 |
type | 參數在構造函數中的數據類型 |
name | 參數在構造函數中的名稱 |
value | 用於給基本類型和String類型賦值 |
ref | 能將其他類型的bean賦值給屬性 |
依賴注入方式二 : set方法注入
需要注入的成員提供set方法。
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl implements AccountService {
private String name;
private Double money;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setMoney(Double money) {
this.money = money;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void saveAccount() {
System.out.println("賬戶信息爲 姓名:"+name+" 生日:"+birthday+" 餘額:"+money);
}
}
通過配置文件給bean中屬性賦值,使用set方法的方式。
<bean id="accountService" class="com.liang.service.impl.AccountServiceImpl">
<property name="name" value="張三"></property>
<property name="birthday" ref="birthday"></property>
<property name="money" value="100.0"></property>
</bean>
<bean id="birthday" class="java.util.Date"></bean>
property標籤屬性說明
屬性 | 功能 |
---|---|
name | 類中set方法後面的部分(首字母小寫) |
ref | 將其他bean類型賦值給屬性 |
value | 將基本類型和String類型賦值給屬性 |
依賴注入方式三 : 使用p名稱空間注入數據
在xml配置文件中導入p名稱空間,使用p:屬性名 來注入數據,其本質是set方式注入。
/**
* 賬戶的業務層實現類
*/
public class AccountServiceImpl implements AccountService {
private String name;
private Double money;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setMoney(Double money) {
this.money = money;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void saveAccount() {
System.out.println("賬戶信息爲 姓名:"+name+" 生日:"+birthday+" 餘額:"+money);
}
}
配置文件:引入p名稱空間: xmlns:p=“http://www.springframework.org/schema/p”
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="com.liang.service.impl.AccountServiceImpl" p:name="張三" p:money="100.0" p:birthday-ref="birthday"></bean>
<bean id="birthday" class="java.util.Date"></bean>
</beans>
集合類型屬性注入
變量的數據類型都是集合類型,例如數組、List、 Set、 Map、 Properties類型的變量注入。
public class AccountServiceImpl implements AccountService {
private String[] str;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
public void setStr(String[] str) {
this.str = str;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void saveAccount() {
System.out.println("數組:" + str);
System.out.println("List:" + list);
System.out.println("Set:" + set);
System.out.println("Map:" + map);
System.out.println("Properties" + properties);
}
}
配置文件
<bean id="accountService" class="com.liang.service.impl.AccountServiceImpl">
<!--給數組注入數據-->
<property name="str">
<set>
<value>娃哈哈</value>
<value>AD鈣</value>
</set>
</property>
<!--注入list集合數據-->
<property name="list">
<list>
<value>小河</value>
<value>小馬</value>
</list>
</property>
<!--注入set集合數據-->
<property name="set">
<set>
<value>張三</value>
<value>李四</value>
</set>
</property>
<!--注入map集合數據-->
<property name="map">
<map>
<entry key="key1" value="Values1"></entry>
<entry key="key2" value="Values2"></entry>
<entry key="key3">
<value>Values3</value>
</entry>
</map>
</property>
<!--注入properties數據-->
<property name="properties">
<props>
<prop key="testA">A</prop>
<prop key="testB">B</prop>
</props>
</property>
</bean>
測試
@Test
public void configTest()
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService = (AccountService)applicationContext.getBean("accountService");
System.out.println(accountService);
accountService.saveAccount();
}
在注入集合數據時,只要結構相同,則標籤可以互換。
那麼本文開始提到的問題則可以通過上述方式進行解決
。例如:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void saveAccount() {
accountDao.saveAccount();
}
}
配置文件
<bean id="accountDao" class="com.liang.dao.impl.AccountDaoImpl"></bean>
<bean id="accountService" class="com.liang.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
測試
@Test
public void configTest()
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService = (AccountService)applicationContext.getBean("accountService");
System.out.println(accountService);
accountService.saveAccount();
}