Spring 是当前主流的Java Web 开发框架,它是为了解决企业应用开发的复杂性问题而产生的。
1、1Spring 概述
1.1.1 什么是Spring
Spring 是由Rod Johnson 组织和开发的一个分层的Java SE/EE full一stack (一站式)轻量级开源框架,它以loC ( Inversion of Control ,控制反转)和AOP ( Aspect Oriented Programming ,面向切面编程)为内核,使用基本的JavaBean 来完成以前只可能由EJB ( Enterprise Java Beans ,Java 企业Bean) 完成的工作,取代了EJB 的雍肿、低效的开发模式。
Spring 致力于Java EE 应用各层的解决方案,在表现层它提供了Spr i ng MVC 以及与Struts框架的整合功能;在业务逻辑层可以管理事务、记录日志等;在持久层可以整合MyBatis 、Hibernate 、JdbcTemplate 等技术。因此,可以说Spring 是企业应用开发很好的"一站式"选择。虽然Spring 贯穿于表现层、业务逻辑层和持久层,但它并不想取代那些已有的框架,而是以高度的开放性与它们进行无缝整合。
1.1.2 Spring 框架的优点
Spring 不仅可以用于服务器端开发,也可以应用于任何Java 应用的开发中。
. 非侵入式设计
Spring 是一种非侵入式( non-invasive )框架,它可以使应用程序代码对框架的依赖、最小化。
. 方便简单、简化开发
Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring 容器管理,大大地降低了组件之间的耦合性。
. 支持AOP
Spring 提供了对AOP 的支持,它允许将一些通用任务,如安全、事务、曰志等进行集中式处理,从而提高了程序的复用性。
. 支持声明式事务处理
只需要通过配置就可以完成对事务的管理,而无须手动编程。
· 方便程序的测试
Spring 提供了对Junit4 的支持,可以通过注解方便地测试Spring 程序。
. 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts 、Hibernate 、MyBatis 、Quartz 等)的直接支持。
· 降低Java EE API 的使用难度
Spring 对Java EE 开发中非常难用的一些API (如JDBC 、JavaMail 等),都提供了封装,使这些API 应用难度大大降低。
1.1.3 Spring 的体系结构
Spring 框架采用的是分层架构,它一系列的功能要素被分成20 个模块
1: Core Container (核心容器)
Spring 的核心容器是其他模块建立的基础,它主要由Beans 模块、Core 模块、Context 模块、Context- support 模块和SpEL ( Spring Expression Language , Spring 表达式语言)模块组成,具体介绍如下:
• Beans 模块:提供了BeanFactory ,是工厂模式的经典实现, Spring 将管理对象称为Bean。
• Core 核心模块:提供了Spring 框架的基本组成部分,包括loC 和DI 功能。
• Context 上下文模块: 建立在Core 和Beans 模块的基础之上,它是访问定义和配置的任何对象的媒介。其中ApplicationContext 接口是上下文模块的焦点。
• Context-support 模块:提供了对第三方库嵌入Spring 应用的集成支持,比如缓存( EhCache 、Guava 、JCache) 、邮件服务(JavaMail) 、任务调度( CommonJ 、Quartz) 和模板引擎( FreeMarker 、JasperReports 、速率)。
• SpEL 模块:是Spring 3 . 0 后新增的模块,它提供了Spring Expression Language 支持,是运行时查询和操作对象图的强大的表达式语言。
2. Data Access/lntegration (数据访问l集成)
数据访问/集成层包括JDBC 、ORM 、OXM 、JMS 和Transactions 模块,真体介绍如下。
• JDBC 模块:提供了一个JDBC 的抽象层,大幅度地减少了在开发过程中对数据库操作的编码。
.ORM 模块:对流行的对象关系映射API ,包括JPA 、JDO 和Hibernate 提供了集成层支持。
.OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如JAXB 、Castor 、XMLBeans 、JiBX 和XStream 。
• JMS 模块:指Java 消息传递服务,包含使用和产生信息的特性,自4 . 1 版本后支持与Spring-message 模块的集成。
• Transactions 事务模块:支持对实现特殊接口以及所有POJO 类的编程和声明式的事务管理。
3. Web
Spring 的Web 层包括WebSocket 、Servlet 、Web 和Portlet 模块,具体介绍如下。
• WebSocket 模块: Spring 4.0 以后新增的模块,它提供了WebSocket 和SockJS 的实现,以及对STOMP 的支持。
• Servlet 模块:也称为Spring-webmvc 模块,包含了Spring 的模型一视图一控制器(MVC)和REST Web Services 实现的Web 应用程序。
• Web 模块:提供了基本的Web 开发集成特性,例如: 多文件上传功能、使用Servlet 监听器来初始化loC 容器以及Web 应用上下文。
• Portlet 模块:提供了在Portlet 环境中使用MVC 实现,类似Servlet 模块的功能。
4. 其他模块
Spring 的其他模块还有AOP 、Aspects 、Instrumentation 以及Test 模块,具体介绍如下。
• AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
• Aspects 模块:提供了与AspectJ 的集成功能, AspectJ 是一个功能强大且成熟的面向切面编程(AOP) 框架。
• Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
• Messaging 模块: Spring 4.0 以后新增的模块,它提供了对消息传递体系结构和协议的支持。
• Test 模块:提供了对单元测试和集成测试的支持。
1.1.4 Spring 的下载及目录结构
Spring 开发所需的JAR 包分为两个部分
1. Spring 框架包
Spring 4.3.6 版本的框架压缩包,名称为spring-framework-4.3.6.RELEASE-dist. zip ,此
压缩包可以通过地址’'http://repo.spring.io/simple/libs-release-Iocal/org/springframework/spring/
4.3.6.RELEASE/" 下载。下载完成后,将压缩包解压到自定义的文件夹中,解压后的文件目录结构如图
打开libs 目录可以看到60 个JAR 文件
libs 目录中的JAR 包分为三类,其中
以RELEASE . jar 结尾的是spring框架class 文件的JAR 包;
以RELEASE - javadoc. jar 结尾的是Spring框架API 文档的压缩包;
以RELEASE-sources . jar 结尾的是Spring 框架源文件的压缩包。
整个Spring 框架由20 个模块组成,该目录下Spring 为每个模块都提供了这三类压缩包。
在libs 目录中,有四个Spring 的基础包,它们分别对应Spring 核心容器的四个模块,具体介绍如下。
• spring-core-4.3 . 6 . RELEASE . jar: 包含Spring 框架基本的核心工具类, Spring 其他组件都要用到这个包里的类,是其他组件的基本核心。
• spring-beans-4 . 3 . 6.RELEASE.jar: 所有应用都要用到的JAR 包,它包含访问配置文件、
创建和管理Bean 以及进行Inversion of Control(loC)或者Dependency Injection(DI)操作相关的所有类。
• spring-context -4.3.6.RELEASE.jar: Spring 提供了在基础loC 功能上的扩展服务,还提供了许多企业级服务的支持,如邮件服务、任务调度、JNDI 定位、EJB 集咸、远程访问、缓存以及各种视图层框架的封装等。
• spring-expression-4.3 . 6.RELEASE.jar: 定义了Spring 的表达式语言。
2. 第三方依赖包
在使用Spring 开发时,除了要使用自带的JAR 包外, Spring 的核心容器还需要依赖
commons.logging .JAR 包。该JAR 包可以通过网"http://commons.apache . org/proper/commons-logging/download_logging.cgi" 下载。下载完成后,会得到一个名为ommonslogging-1 . 2-bin.zit 的压缩包。将压缩包解压到自定义目录后,即可找到commons-Iogging-1 .2.jar。
初学者学习Spring 框架时,只需将Spring 的4 个基础包以及commons-logging-1.2 . jar复制到项目的lib 目录,并发布到类路径中即可。
1.2 Spring 的核心容器
Spring 框架的主要功能是通过其核心容器来实现的,因此在正式学习Spring 框架的使用之前,有必要先对其核心容器有一定的了解。Spring 框架提供了两种核心容器,分别为BeanFactory和ApplicationContext。
1.2.1 BeanFactory
BeanFactory 由org.springframework.beans.facytory . BeanFactory 接口定义,是基础类型的loC 容器它提供了完整的loC 服务支持。简单来说, BeanFactory 就是一个管理Bean 的工厂,它主要负责初始化各种Bean ,并调用它们的生命周期方法。
BeanFactory 接口提供了几个实现类,其中最常用的是org. Springframework. beansfactory.xml.XmIBeanFactory ,该类会根据XML 配置文件中的定义来装配Bean 。
创建BeanFactory 实例时,需要提供Spring 所管理容器的详细配置信息,这些信息通常采用XML 文件形式来管理,其加载配置信息的语法如下。
BeanFactory beanFactory =new Xm lBeanFactory( New FileSystemResource{“F: /applicationContext . xml”)) ;
这种加载方式在实际开发中并不多用。
1.2.2 ApplicationContext
ApplicationContext 是BeanFactory 的子接口,也被称为应用上下文,是另一种常用的Spring核心容器。它由org.springframework . context. ApplicationContext 接口定义,不仅包含了BeanFactory 的所有功能,还添加了对国际化、资源访问、事件传播等方面的支持。
创建ApplicationContext 接口实例,通常采用两种方法,具体如下。
1. 通过ClassPathXmlApplicationContext 创建
ClassPathXmlAp~licationContext 会从类路径classPath 中寻找指定的XML 配置文件,找到并装载完成ApplicationContext 的实例化工作,其使用语法如下。
ApplicationContext applicationContext =new ClassPathXmlApplicationContext(String configLocation) ;
上述代码中, configLocation 参数用于指定Spring 配置文件的名称和位置。如果其值为"applicationContext.xml" , Spring 会去类路径中查找名称为applicationContext. xml 的配置文件。
2. 通过FileSystemXmlApplicationContext 创建
FileSystemXmlApplicationContext 会从指定的文件系统路径(绝对路径)中寻找指定的XML配置文件,找到并装载完成ApplicationContext 的实例化工作,其使用语法如下。
ApplicationContext applicationContext =new FileSystemXmlApplicationContext(String configLocation);
与ClassPathXmlApplicationContext 有所不同的是,在读取Spring 的配置文件时,FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,例如"D:/workspaces/app I icationContext. xml" 。如果在参数中写的不是绝对路径,那么方法调用的时候,会默认用绝对路径来找。这种采用绝对路径的方式,会导致程序的灵活性变差,所以这个方法一般不推荐使用。
3.基于ContextLoader Listener 实现
在使用Spring 框架时,可以通过实例化其中任何一个类来创建ApplicationContext容器。通常在Java 项目中,会采用通过ClassPathXmlApplicationContext 类来实例化pplicationContext 容器的方式,而在Web 项目中, ApplicationContext 容器的实例化工作会交由Web 服务器来完成。Web 服务器实例化ApplicationContext 容器时,通常会使用基于ContextLoader Listener 实现的方式,此种方式只需要在web.xml 中添加如下代码。
contextConfigLocation
**classpath:spring/applicationContext.xml**
**org.springframework.web.context.ContextLoaderListener**
创建Spring 容器后,就可以获取Spring 容器中的Bean。Spring 获取Bean 的实例通常采用以下两种方法。
• Object getBean(String name): 根据容器中Bean 的id 或name 来获取指定的Bean ,获取之后需要进行强制类型转换。
• T getBean(Class requiredType) : 根据类的类型来获取Bean 的实例。由于此方法为泛型方法,因此在获取Bean 之后不需要进行强制类型转换。
1.3 Spring 的入门程序(IOC示例)
( 1 )在Eclipse 中,创建一个名为chapter01 的Web 项目,将Spring 的4 个基础包以及commons-Iogging 的JAR 包复制到lib 目录中,并发布到类路径下
( 2 ) 在s rc 目录下,创建一个com . itheima . ioc 包,并在包中创建接口UserDao ,然后在接口中定义一个say方法
UserDao.java
package com . itheima . ioc;
public interface UserDao{
public void say() ;
}
(3 )在com.itheima.ioc 包下,创建UserDao 接口的实现类UserDaolmpl ,该类需要实现接口中的sayO方法,并在方法中编写一条输出语句
UserDaolmpl.java
package com.itheima.ioc;
public class UserDaolmpl implements UserDao {
public void say() {
System.out.println(“userDao say hello World!”);
}
}
(4 )在src 目录下,创建Spring的配置文件applicationContext. xml ,并在配置文件中创建一个id 为userDao 的Bean
applicationContext.xml
** **
Spring 配置文件的名称可以自定义,通常在实际开发中, 都会将配置文件命名为applicationContext.xml (有时也会命名为beans.xml) 。
( 5 ) 在com . itheima.ioc 包下,创建测试类Test loC ,并在类中编写main方法。在main方法中,需要初始化Spring 容器,并加载配置文件, 然后通过Spring 容器获取userDao 实例( 即Java 对象),最后调用实例中的say()方法
TestloC. java
package com.itheima.ioc;
import org.springframework.context .ApplicationContext ;
import org . springframework.context . support . ClassPathXmlApplicationContext ;
public class TestloC (
public static void main(String[] args)
/ /1.初始化spring 容器,加载配置文件
ApplicationContext applicationContext =new ClassPathXmlApplicationContext( "applicationContext . xml " );
//2 . 通过容器获取userDao 实例
UserDao userDao = (UserDao) app1icationContext .getBean(“userDao”) ;
//3 . 调用实例巾的say ()方法
userDao . say();
}}
执行程序后,控制台的输出结果
1.4 依赖注入
1.4.1 依赖注入的概念
依赖注入( Dependency Injection ,简称DI) 与控制反转(loC) 的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。
当某个Java 对象(调用者)需要调用另一个Java 对象(被调用者,即被依赖对象)时,在传统模式下,调用者通常会采用"new 被调用者"的代码方式来创建对象,这种方式会导致调用者与被调用者之间的捐合性增加,不利于后期项目的升级和维护。
在使用Spring 框架之后,对象的实例不再由调用者来创建,而是由Spring 容器来创建,Spring 容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移到了Spring 容器,控制权发生了反转,这就是Spring 的控制反转。
从Spring 容器的角度来看, Spring 容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring 的依赖注入。
1.4.2 侬赖注入的实现方式(DI示例)
依赖注入的作用就是在使用Spring 框架创建对象时,动态地将其所依赖的对象注入Bean组件中,其实现方式通常有两种,一种是属性setter 方法注入,另一种是构造方法注入,具体介绍如下。
·属性setter 方法注入:指loC 容器使用****setter 方法注入被依赖的实例。通过调用无参构造器或无参静态工厂方法实例化Bean 后,调用该Bean 的setter 方法,即可实现基于setter 方法的y依赖注入。
.构造方法注入:指loC 容器使用构造方法注入被依赖的实例。基于构造方法的依赖注入通过调用带参数的构造方法来实现,每个参数代表着一个依赖。
了解了两种注入方式后,下面以属性setter 方法注入的方式为例,讲解一下Spring 容器在应用中是如何实现依赖注入的。
( 1 )在com . itheima.ioc 包中,创建接口UserService ,在接口中编写一个sayO方法
UserService.java
package com.itheima. ioc;
public interface UserService{
public void say();
}
(2 )在com . itheima .ioc 包中,创建UserService 接口的实现类UserServicelmpl , 在类中声
明userDao 属性,并添加属性的setter 方法
UserServicelmpl .java
package com.itheima.ioc;
public class UserServicelmp limplements UserService{
/ /声明UserDao 属性
private UserDao userDao;
/ /添加UserDao 属性的setter 方法,用于实现依赖注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/ /实现的接口中方法
public void say() {
/ /调用userDao 中的say ()方法,并执行输出语句
this.userDao.say();
System.out.println(“userService say hello World !”);
}
}
(3 )在配置文件appI icationContext. xm I 中,创建一个id 为userService 的Bean ,该Bean
用于实例化UserServicelmpl 类的信息,并将userDao 的实例注入到 userService 中
(4 )在com . itheima . ioc 包中,创建测试类Tes1DI,来对程序进行测试
package com.itheima.ioc;
import org.springframework.context.App1icationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDI {
public static void main(String[) args) (
//1.初始化spring 容器,加载配置文件
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext(“applicationContext.xml”);
//2. 通过容器获取UserService 实例
UserService userService =
(UserService ) applicationContext.getBean(“userService”);
//3. 调用实例中的say() 方法
userService.saY();
}
}
(5 )执行程序后,控制台的输出结果