SSM框架实战系列之七_Spring框架
从本节开始,我们将分别讲解Spring框架、SpringMVC框架、MyBatis框架。
由于之前在搭建Maven项目时,已经在pom.xml文件中指定了所有必需的软件依赖,所以后面就只讲解这些框架怎么应用。
一、什么是Spring框架?
Spring框架是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器框架。
J2EE早先提供了企业级应用开发框架EJB,然而这个框架太重;学习EJB的高昂代价,和极低的开发效率,极高的资源消耗,都造成了EJB的使用困难;Spring出现的初衷就是为了解决类似的这些问题。
Spring的一个最大的目的就是使J2EE开发更加容易;Spring与Struts、Hibernate等单层框架不同的是,Spring致力于提供一个以统一的、高效的方式构造整个应用,并且可以将单层框架以最佳的组合揉和在一起,建立一个连贯的体系。
Spring框架的架构如下图所示:
从图中可以看到,Spring框架拆分得比较细,从下往上看,“Core Container(核心容器)”部分是Spring框架的内核,再上一层就是“AOP(面向切面编程)”部分,再上一层是Web部分和数据处理部分。
当前Spring框架版本为4。
二、Spring框架的主要特性
Spring框架有几个主要特性,分别是:控制反转(IoC)、依赖注入(DI)、面向切面编程(AOP)。
1、控制反转
假设有一家汉堡店的软件系统中,设计了汉堡类和三个子类(鸡腿堡、牛肉堡、鱼肉堡)。
以前我们创建对象通常这么写:Hamburger hamburger = new FishHamburger();
这种情况下,对象的创建由应用程序来完成,主要缺点是代码中硬编码了子类,代码的灵活性较差,例如要修改成吃另一种汉堡,就必须修改源代码。
在引入Spring框架后,对象的创建由Spring框架负责,应用程序不再负责对象的创建,这就叫控制反转,即控制权从应用程序转给了Spring框架。
在Spring配置文件中这么写:
<bean id="hamburger" class="FishHamburger" />
今后如果要换成另一种汉堡,修改Spring配置文件即可。
2、依赖注入
假设在上述汉堡店的软件系统中,汉堡的配料必须用到番茄酱,而番茄酱有三种:甜番茄酱、酸番茄酱、辣番茄酱。
以前我们是这么写的:
public class Hamburger {
private Ketchup ketchup = new SweetKetchup();
}
这样写实际上汉堡类中也是硬编码了番茄酱类的子类,如果换一种酱,还是需要修改源代码。
“依赖注入”中的“依赖”,表示一个类使用了另一个类作为属性,“注入”,表示为属性赋值。
使用了依赖注入之后,应用程序不需要再为属性赋值:
public class Hamburger {
private Ketchup ketchup;
}
而是在Spring框架的配置文件中使用依赖注入,即使用property定义属性,ref表示属性的值来源于另一个bean:
<bean id="ketchup" class="SweetKetchup" />
<bean id="hamburger" class="FishHamburger" >
<property name="ketchup" ref="ketchup" />
</bean>
这里还必须强调的是,编程中应依赖于接口编程,而不应依赖于实现类,例如在我的业务逻辑层类中,会使用到数据处理层,此时应该为数据处理层定义接口,然后在业务逻辑层中,定义接口类型的属性。
例如SchoolDao接口中有增删改查方法,然后又编写了一个实现类SchoolDaoImpl。
此时,SchoolServiceImpl类的代码应为:
public class SchoolServiceImpl {
private SchoolDao schoolDao; // 依赖于接口而不应依赖于实现类
}
3、面向切面编程
面向切面编程,即AOP(Aspect Oriented Programming)。所谓切面,是指每个模块都要用到的通用功能,以前可能是在每个模块中都复制粘贴类似的代码,而面向切面编程,就是将这些通用代码抽取出来,通过定义切面的方式织入特定位置。这些通用功能包括事务、日志等。
三、Web项目中加载Spring框架
在Web项目中可以通过配置web.xml文件来加载Spring框架。
通常有两种加载方式:
1、Servlet方式
在web.xml中添加如下Servlet定义:
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
ContextLoaderServlet类会读取Spring框架的配置文件(默认为applicationContext.xml),并根据配置文件初始化Spring框架。
2、监听器方式
监听器是较新的Web版本才支持的功能,配置如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderListener类与ContextLoaderServlet类功能类似,都可加载配置文件,并初始化Spring框架。此处还配置了配置文件的路径(配置了类路径下,config目录中所有以spring开头的配置文件)。
在web.xml中,最好再指定一下字符编码:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name >
<url-pattern>/*</url-pattern>
</filter-mapping>
四、Spring配置文件
在resources文件夹下,新建一个config文件夹,并在其中添加一个名为spring-beans.xml的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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.hanhf" />
</beans>
这里我们不准备使用传统的在Spring配置文件定义bean的方式,而是采用了注解驱动的开发,即控制反转和依赖注入都由注解来完成,下一节会仔细讲解注解的使用。
由于采用了注解驱动的开发,所以定义了<mvc:annotation-driven />即注解驱动,<context:component-scan base-package="com.hanhf" />即组件扫描,表示扫描根包下的所有类并解析其中的注解。
最后,贴出代码清单。
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>ssmprj</display-name>
<!-- 加载spring框架 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
spring-beans文件:
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.hanhf" />
</beans>
项目的目录结构: