一. 需求产生
现在我们有两个层:userDao和userService
userDaoImpl:
package com.guazi.Service.Impl;
import com.guazi.Service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void save() {
// 加载xml配置文件
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过id标识获取类
UserDao userDao = (UserDao) app.getBean("userDao");
// 实现类方法
System.out.println(userDao.save(););
}
}
userService:
package com.guazi.Service.Impl;
import com.guazi.Dao.UserDao;
import com.guazi.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements UserService {
@Override
public void save() {
// 加载xml配置文件
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过id标识获取类
UserDao userDao = (UserDao) app.getBean("userDao");
// 实现类方法
System.out.println(userDao.save(););
}
}
在xml中配置bean标签:
<bean id="userDao" class="com.guazi.Dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl"></bean>
创建一个测试文件来跑userService:
package com.guazi.demo;
import com.guazi.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
public static void main(String[] args){
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= (UserService) app.getBean("userService");
userService.save();
}
}
结果如下:
save running
现在代码的逻辑是,先通过spring得到userService的对象,调用userService的save方法,然后发现save中会用到userDao,然后再通过spring去调用userDao。这里spring被调用了两次。
但是,我们需要用到的其实只有userService。而且这样的配置方式增加了程序的耦合。
这就需要再我们通过spring调用userService,然后,在spring内部调用userDao。这里我们称,userService需要userDao的依赖注入。
二. 依赖注入
1. 有参构造方法
先将userService改成有参构造的形式:
package com.guazi.Service.Impl;
import com.guazi.Dao.UserDao;
import com.guazi.Service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
@Override
public void save() {
userDao.save();
}
}
传统的xml配置方法,spring找的是无参构造方法。这里需要进行配置让其找到有参构造。
<bean id="userDao" class="com.guazi.Dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
name指的是构造函数里的参数,ref指的是spring中的对象引用。
2. set方法注入
我们将userService的代码改为:
package com.guazi.Service.Impl;
import com.guazi.Dao.UserDao;
import com.guazi.Service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
其中的userDao我们在Spring中注入:
<bean id="userDao" class="com.guazi.Dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
其中,name属性的userDao指的是,将setUserDao中的UserDao的第一个字母改成小写。
在xml中,将我们的set注入改一种写法就变成了p命名空间注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.guazi.Dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl" p:userDao-ref="userDao"/>
</beans>
加了一个xmlns:p,然后把userService中的userDao属性用p空间进行注入。
由于是引用的xml中其他的类,所以要用userDao-ref。
这种方式不需要自标签,所以结尾加/。
三. 其他依赖注入
依赖注入的东西一共有三种:
- 普通数据类型
- 集合数据类型
- 引用数据类型(例如上述的userDao)
这里我们再看另外的两种:
1. 普通数据类型
userService中,增加name和age变量,并用set注入方式:
package com.guazi.Service.Impl;
//import com.guazi.Dao.UserDao;
import com.guazi.Service.UserService;
import java.sql.SQLOutput;
public class UserServiceImpl implements UserService {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
// userDao.save();
System.out.println("name"+name);
System.out.println("age"+age);
}
}
修改xml文件:
<bean id="userDao" class="com.guazi.Dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<property name="name" value="zhang san"></property>
<property name="age" value="18"></property>
</bean>
引用数据类型赋值用的是ref,普通数据类型用value。
运行结果:
namezhang san
age18
2. 集合数据类型
演示三种集合类型:
- list
- map
- properties
(1)list
userService:
public class UserServiceImpl implements UserService {
private List list;
public void setList(List list) {
this.list = list;
}
@Override
public void save() {
// userDao.save();
System.out.println(list);
}
}
xml文件:
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
运行结果:
[1, 2, 3]
(2)map
userService:
public class UserServiceImpl implements UserService {
private Map map;
public void setMap(Map map) {
this.map = map;
}
@Override
public void save() {
// userDao.save();
System.out.println(map);
}
}
这里我创建了一个user类,里面有name和age两个属性,然后配置上getter、setter和tostring。
xml:
<!-- map的创建-->
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<property name="map">
<map>
<entry key="user1" value-ref="user1"></entry>
<entry key="user2" value-ref="user2"></entry>
</map>
</property>
</bean>
<!-- user的创建-->
<bean name="user1" class="com.guazi.domain.User">
<property name="name" value="zhang san"></property>
<property name="age" value="18"></property>
</bean>
<bean name="user2" class="com.guazi.domain.User">
<property name="name" value="li si"></property>
<property name="age" value="24"></property>
</bean>
结果:
{user1=User{name='zhang san', age=18}, user2=User{name='li si', age=24}}
(3)properties
userService:
public class UserServiceImpl implements UserService {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public void save() {
// userDao.save();
System.out.println(properties);
}
}
<bean id="userService" class="com.guazi.Service.Impl.UserServiceImpl">
<property name="properties">
<props>
<prop key="username">zhangsan</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
结果:
{password=123456, username=zhangsan}