在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();
}