Spring框架学习记录 2 依赖注入

示例

(1)创建接口 UserService 以及实现类 UserServiceImple

UserService:

package Service;

public interface UserService {
	public void say();
}

UserServiceImple:

package Service.Implement;

import Dao.UserDao;
import Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImple implements UserService {

	@Override
	public void say() {
		ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userDao = (UserDao) app.getBean("userDao");
		userDao.say();
	}

}

(2)在 xml 配置文件中增加 UserServiceImple 的配置信息

<bean id="userService" class="Service.Implement.UserServiceImple"/>

(3)创建 UserController 类进行测试

import 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.say();
	}
}

问题分析

这种做法将 UserServiceImple 和 UserDaoImple 的实例都存在 Spring 容器中,在程序中完成了二者的组装,而在 Controller 中只需要使用 UserServiceImple ,而不需要关心 UserDaoImple 如何获取,故考虑在容器内部完成二者的组装


依赖注入(DI)

依赖注入是 Spring框架中IoC的具体体现

在编写程序时,通过控制反转,将对象的创建交给了 Spring 来控制,但代码中一定还会存在依赖的情况,如业务层调用持久层的方法,依赖注入可以让 Spring 自动的向某个对象提供它需要的对象


bean 的依赖注入方式

(1)构造方法

修改 UserServiceImple ,增加无参和含参数 UserDao 的构造方法,删除不必要的代码

package Service.Implement;

import Dao.UserDao;
import Service.UserService;

public class UserServiceImple implements UserService {

	private UserDao userDao;

	public UserServiceImple() {
	}

	public UserServiceImple(UserDao userDao) {
		this.userDao = userDao;
	}

	@Override
	public void say() {
		userDao.say();
	}

}

在 xml 配置文件中增加依赖注入的配置信息,用 <constructor-arg> 标签进行构造方法的参数传入

用 name 指定构造方法参数的形参名

用 ref 指定传入的对象的 id,这里需要传入容器中 UserDaoImple 的实例,故为对应 bean 的 id

<bean id="userDao" class="Dao.Implement.UserDaoImple"/>

<bean id="userService" class="Service.Implement.UserServiceImple">
    <constructor-arg name="userDao" ref="userDao"/>
</bean>

(2)set 方法

修改 UserServiceImple ,增加 UserDao 成员和 set 方法,删除不必要的代码

package Service.Implement;

import Dao.UserDao;
import Service.UserService;

public class UserServiceImple implements UserService {

	private UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Override
	public void say() {
		userDao.say();
	}

}

在 xml 配置文件中增加依赖注入的配置信息,用 <property> 标签进行属性注入

用 name 指定该类中相应的 set 方法名后面的字段,并将第一个字母改为小写,如该类中的 setUserDao 方法,name 即为 userDao,而并非是该类中成员变量 userDao,尽管二者相同

用 ref 指定需要注入的对象的 id,与上文中的 ref 同理,填写容器中相应 bean 的 id 即可 

<bean id="userDao" class="Dao.Implement.UserDaoImple"/>

<bean id="userService" class="Service.Implement.UserServiceImple">
    <property name="userDao" ref="userDao"/>
</bean>

经过这样的配置后,UserController 中调用 getBean 方法获取 UserServiceImple 对象时,该对象便已经自动装载了 UserDaoImple 实例,但如果直接使用 new 创建 UserServiceImple 对象,则没有这个效果,也就是说,只有容器内的对象才能自动装载需要的实例

(3)p命名空间注入

该方法与 set 方法类似,需要在 UserServiceImple 类中创建 set 方法

区别在于 xml 配置文件中不再使用 <property> 标签进行属性注入,而是在 <bean> 标签中通过属性的方式进行注入

首先声明p命名空间,在 xml 配置文件的 <beans> 标签上增加如下代码

xmlns:p="http://www.springframework.org/schema/p"

再使用 p:userDao-ref 属性指定需要注入的对象,同样的,这里的 userDao 也是与 set 方法名后面的字段的首字母改为小写保持一致

完整 xml 配置文件如下:

<?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="Dao.Implement.UserDaoImple"/>

    <bean id="userService" class="Service.Implement.UserServiceImple" p:userDao-ref="userDao"/>

</beans>

bean 的依赖注入的数据类型

其中,引用数据类型的注入即为 bean 对象注入,刚刚已经做过详细叙述,不再赘述,重点介绍普通数据类型和集合数据类型

(1)普通数据类型

在 UserDaoImple 中增加两个普通数据类型的成员

对于 set 方法注入,需对每个数据成员创建 set 方法

package Dao.Implement;

import Dao.UserDao;

public class UserDaoImple implements UserDao {

	private String userName;
	private int age;

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public void say() {
		System.out.println(userName + " " + age);
		System.out.println("喵~");
	}

}

在 xml 配置文件中使用 <property> 进行属性注入,使用 value 指定注入的内容

<bean id="userDao" class="Dao.Implement.UserDaoImple">
    <property name="userName" value="猫头夜鹰"/>
    <property name="age" value="18"/>
</bean>

对于构造方法注入,需创建相应的构造方法

package Dao.Implement;

import Dao.UserDao;

public class UserDaoImple implements UserDao {

	private String userName;
	private int age;

	public UserDaoImple(String userName, int age) {
		this.userName = userName;
		this.age = age;
	}

	@Override
	public void say() {
		System.out.println(userName + " " + age);
		System.out.println("喵~");
	}

}

在 xml 配置文件中使用 <constructor-arg> 传入参数,使用 value 指定传入内容

<bean id="userDao" class="Dao.Implement.UserDaoImple">
    <constructor-arg name="userName" value="猫头夜鹰"/>
    <constructor-arg name="age" value="18"/>
</bean>

(2)集合数据类型

集合的种类较多,以 List 、Map 、Properties 三种集合为例,介绍集合注入

创建这三种类型的数据成员,并创建它们的 set 方法

package Dao.Implement;

import Dao.UserDao;
import Entity.User;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class UserDaoImple implements UserDao {

	private List<String> strList;
	private Map<String, User> userMap;
	private Properties properties;

	public void setStrList(List<String> strList) {
		this.strList = strList;
	}

	public void setUserMap(Map<String, User> userMap) {
		this.userMap = userMap;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	@Override
	public void say() {
		System.out.println(strList);
		System.out.println(userMap);
		System.out.println(properties);
		System.out.println("喵~");
	}

}

其中,Map 中含有实体类 User

package Entity;

public class User {
	private String userName;
	private int age;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User{" + "userName='" + userName + '\'' + ", age=" + age + '}';
	}
}

在 xml 配置文件中使用 <property> 进行属性注入,<property> 标签内部填写集合的具体内容

对于 List 、Map 、Properties 三种集合,分别使用 <list> 、<map> 、<props> 进行创建,在这些标签内部填写集合的具体内容,若为普通数据类型,则用 <value> ,若为键值对,则用 <entry> 并用属性 key 和 value 指定键和值,若键或值为引用类型,则使用 key-ref 或 value -ref 指定,若为 properties ,则用 <prop> 并用 key 指定键,而内容填写在标签中

<bean id="userDao" class="Dao.Implement.UserDaoImple">
    <property name="strList">
        <list>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </list>
    </property>
    <property name="userMap">
        <map>
            <entry key="user1" value-ref="user1"/>
            <entry key="user2" value-ref="user2"/>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="p1">result1</prop>
            <prop key="p2">result2</prop>
            <prop key="p3">result3</prop>
        </props>
    </property>
</bean>

<bean id="user1" class="Entity.User">
    <property name="userName" value="皮卡丘"/>
    <property name="age" value="3"/>
</bean>

<bean id="user2" class="Entity.User">
    <property name="userName" value="卡比兽"/>
    <property name="age" value="5"/>
</bean>

引入其他配置文件(分模块开发)

在实际开发中,配置内容会非常多,配置文件的体积较大,为了便于管理,可以将配置文件拆分保存,并在 Spring 的主配置文件中 <import> 标签进行加载

<import resource="applicationContext-product.xml"/>
<import resource="applicationContext-user.xml"/>

在加载主配置文件时,这些分文件的内容也会一同加载

猜你喜欢

转载自blog.csdn.net/qq_25274377/article/details/120250933