一、Spring IoC概述
IoC即为控制反转(Inversion of Controll),它用来将对象的创建权反转给(交给)Spring来创建。假如,你现在需要一杯果汁,你没有必要去买果汁机,橙子,准备橙子等操作,而是去超市直接买即可。果汁就相当于你需要使用的对象,而该对象是由果汁厂创建然后由超市提供的,果汁厂就相当于Spring。
二、IoC入门实例
下载Spring的开发包
官方地址
上面的压缩包分别为Spring相关的依赖包,开发包,开发文档以及约束。
创建web项目并导入Jar包
前两个jar包为日志相关的依赖包,分别位于如下路径下:
后面四个依赖包为Spring核心容器相关的必需包。
创建接口和类
package com.shoto.spring.demo1;
/**
* 用户管理DAO层接口
* @author 郑松涛
*
*/
public interface UserDAO {
public void save();
}
package com.shoto.spring.demo1;
/**
* 用户管理DAO层实现类
* @author 郑松涛
*
*/
public class UserDAOImpl implements UserDAO {
private String name;
//依赖注入
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("UserDAOImpl的Save方法执行了。。。" + name);
}
}
编写appliactionContext.xml,将实现类交给Spring管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean definitions here -->
<bean id="userDAO" class="com.shoto.spring.demo1.UserDAOImpl">
<!-- 依赖注入,name为UserDAOImpl中的属性,value则是赋给的值-->
<property name="name" value="张三"/>
</bean>
</beans>
运行测试
/**
* 传统方式,接口与实现类之间有耦合
*/
/*@Test
public void test() {
UserDAO userDAO = new UserDAOImpl();
userDAO.save();
}*/
@Test
public void test01() {
//创建Spring工厂
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean,userDAO为applicationContext对应的bean的id值
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();//输出UserDAOImpl的Save方法执行了。。。张三
}
不同于传统的方式,通过使用创建Spring工厂ApplicationContext来创建Bean,也就是UserDAO的实现类,从而实现了接口与实现类的解耦。
三、Spring IoC容器
结构图
BeanFactory
该类是Spring Ioc容器所定义的最底层接口,是老版本的工厂类。当调用getBean的时候,才会生成类的实例。
AppliactionFactory
ApplicationFactory对BeanFactory接口进行了功能的扩展,其是新版本的工厂类。在大部分工作场景下,都会使用ApplicationFactory作为Spring IoC容器。其在加载配置文件的时候,就会将Spring管理的类都实例化。
其有两个如下的实现类:
1. ClassPathXmlApplicationContext :用于加载类路径下的配置文件
2. FileSystemXmlApplicationContext :用于加载文件系统下的配置文件
四、依赖注入DI
在有IOC的环境的前提下,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。
比如上面我们在配置Bean时,使用到了其子元素<property>来给该Bean对应的类的属性赋值。
五、Spring配置
Schema约束配置(XML具有提示功能)
Bean相关配置
1. 标签的id和name的配置
- id :使用了约束中的唯一约束,里面不能出现特殊字符。
- name :没有使用约束中的唯一约束(理论上可以出现重复的,但是实际开发不能出现的),里面可以出现特殊字符。
比如,可以更改上方的applicationContext.xml中的bean为如下格式。当然一般情况下不推荐这种方式。
另一方面,早在之前Spring与Struts 1整合的时候,配置bean时是不支持如下这种格式的,因为id中存在特殊字符 / 。
<bean id="/user" class=""/>
此时就要改成如下的格式:
<bean name="/user" class=""/>
2. Bean的生命周期的配置
生命周期主要是为了了解Spring IoC容器初始化和销毁Bean的过程,通过对它的学习就可以知道如何在初始化和销毁的时候加入自定义的方法,以满足特定的要求。
它有如下两个生命周期相关的方法:
- init-method:Bean被初始化的时候执行的方法;
- destroy-method:Bean被销毁的时候执行的方法,Bean是单例创建且在工厂关闭是才会调用。
下面演示一下它们的用法:
- 修改applicationContext.xml的配置如下:
<bean id="userDAO" class="com.shoto.spring.demo1.UserDAOImpl" init-method="init" destroy-method="destroy"> <!-- 属性注入,name为UserDAOImpl中的属性,value则是赋给的值--> <property name="name" value="张三"/> </bean>
- 在原有UserDAOImpl类中增加如下两个方法:
public void init() { System.out.println("UserDAOImpl被初始化了。。。"); } public void destroy() { System.out.println("UserDAOImpl被销毁了。。。"); }
- 测试代码:
需要注意的是ApplicationContext的子类才拥有close方法。@Test public void testInitAndDestroy() { //创建Spring工厂 ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取bean,userDAO为applicationContext对应的bean的id值 UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO"); userDAO.save(); //关闭applicationContext工厂,销毁方法才会被调用 applicationContext.close(); }
- 运行结果:
3. Bean的作用范围的配置
Spring提供了4种作用域,它会根据情况来决定是否生成新的对象。可以通过bean标签的scope属性来配置。
- singleton(单例):默认选项,Spring会采用单例模式创建这个对象,即Bean实例;
- prototype(多例):多例模式,Struts2和Spring整合一定会用到,不过现在Struts2很少用了。比如我们希望Struts2中的Action(Struts2的控制层类)有时候需要多个实例,这时就需要将Spring设置为多例模式了;
- request(请求):应用在web项目中,就是在一次请求中Spring会创建一个实例,但是不同点的请求会创建不同的实例;
- session (会话):应用在web项目中,就是在会话过程中Spring只创建一个实例。
我们可以测试一下Spring是否为单例的,在不设置scope属性的情况下,在上面的基础上编写如下测试代码:
//创建Spring工厂
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean,userDAO为applicationContext对应的bean的id值
UserDAO userDAO1 = (UserDAO) applicationContext.getBean("userDAO");
System.out.println(userDAO1);
UserDAO userDAO2 = (UserDAO) applicationContext.getBean("userDAO");
System.out.println(userDAO2);
运行结果: