1、第一部分 Spring 框架的概述Spring 框架是一个轻量级的解决方案和为构建企业级应用程序潜在的一站式服务。然而,Spring 是模块化的,允许你只使用那些你需要的部分,而忽略其他部分。你可以在使用 Struts 时用 Spring 的 IoC 容器,但你也可以只使用Hibernate 集成代码或 JDBC 抽象层。Spring 框架支持声明式事务管理、通过 RMI或 web 服务远程访问你的逻辑,还有多种方式处理数据的持久化。它还提供一个全能的 MVC 框架,并且能将 AOP 移植进你的软件。Spring 被设计为非侵入式的,意味着你的逻辑代码完全不必依赖于此框架。虽然一些基于数据访问
2、技术和 Spring 的库会存在于你的集成层(例如数据访问层) ,但是你的其他代码很容易隔离这些依赖。1.开始使用 Spring这篇手册提供了关于 spring 框架的详细信息,不仅有全面的特性,还有一些关于 spring 包含的潜在的概念(例如“依赖注入”)的背景知识。如果你才刚刚开始,也许你应该从低级版的 “Getting Started“ 手册开始,从http:/spring.io.访问。为了更容易消化,这篇手册是专注于任务式。2.Spring 框架的介绍Spring 框架是一个支持开发 Java 应用程序而提供全面的基础设施的 Java 平台,Spring 处理基础部分从而你可以专注于
3、你的应用。spring 让你能够通过 POJOs 和向 POJOs 应用无侵入的企业服务就可以构建你的应用。这些不仅能应用到 Java SE 而且还能应用到 Java EE.一些作为一个开发者能够使用 spring 平台优势的例子 使 Java 方法可以执行数据库事务而不用去处理事务 API 使本地 Java 方法可以执行远程过程而不用去处理远程 API 使本地 Java 方法可以拥有管理操作而不用去处理 JMXAPI 使本地 Java 方法可以执行消息处理而不用去处理 JMSAPI2.1 依赖注入和控制反转Java 应用程序 一个宽松的专业术语,小到一个 Appletes 大到运行在 n层服
4、务器上的企业级程序通常由互相协作的对象而形成的适当的应用程序。因此在应用中的各种对象之间都会有依赖关系。虽然 Java 平台提供了丰富的应用程序开发功能,但是他缺乏将基本模块组织成一个连贯的整体的技术手段,而是把这些任务留待给开发人员解决。当然,你可以使用各种设计模式,包括工厂模式,抽象工厂模式,构建模式,装饰器模式,还有服务定位器去组织这些多样的类和对象实例从而构成一个应用程序。然而,这些模式是如此的简单:一个使用特定名称的最佳实践,描述了它是干什么的,在哪里使用它,解决的问题是什么等等。模式是形式化的最佳实践,你必须在应用程序中实现自己的业务逻辑。Spring 框架的控制反转(IoC)组件
5、提供一个成文的解决方案将不同部分整合成一个完全能协作运行的应用程序解决了这个问题。spring 框架将那些形式化设计模式总结为一流的对象,你可以在你的应用程序中直接使用他们。众多组织和机构使用 Spring 框架以这种方式来工程师健壮的、可维护的应用程序。2.2 模块Spring 框架的功能组织成大约 20 个模块,这些模块分为核心容器、数据访问/集成、网络、AOP(面向切面的编程)、工具、和测试,如下图所示。2.2.1 核心容器核心容器包括:Core,Beans,Context,和表达式语言Core 和 Beans 模块是框架的基础部分,拥有 IoC 和依赖注入的特性。BeanFactory
6、 是一个复杂的工厂模式的实现,它消除了对于程序化的单例对象的需求,并且允许你将配置信息和规范的依赖关系从你的实际代码逻辑中解耦出来。Context 模块是以 Core 和 Beans 模块为基础构建的,提供一种框架式的对象访问方式,就行 JNDI 注册一样。Context 模块从 Beans 模块继承了它的特性,并增加了对于国际化的支持(用于例如资源包的场景) ,事件传播,资源配置还有透明的上下文,例如一个 Servlet 容器。Context 模块同样支持 Java EE 特性,例如 EJB,JMX 还有基本的远程操作。 ApplicationContext 接口是 Context 模块的核
7、心。表达式语言模块是一种在运行时操作和查询对象的强有力的表达式语言,其语法类似统一的 EL 语言,但是 SpEL 提供了额外的功能。2.2.2 数据防问/集成数据访问/集成层包括:JDBC、ORM、OXM、JMS 和事务等模块JDBC 模块提供了一个去除了单调乏味的 JDBC 代码和解析数据库供应商特定的错误代码的 JDBC 抽象层。ORM 模块将热门的对象关系映射 API 集成,包含 JPA,JDO 和Hibernate。使用 ORM 包你可以将 spring 提供的其他特性与所有的 ORM 框架结合,例如前面提到的简单的声明式事务管理。OXM 模块提供了一个支持对象到 XML 映射的抽象层
8、,包括 JAXB 、Castor、XMLbeans 和 Xstream。JMS 模块支持生产和消费的信息的特性。事务模块支持针对那些实现了特定接口和所有的 POJOs 类的编程式和声明式的事务管理模式2.2.3 Web网络层包括 Web、Web-Servlet、Websocket 和 Web-Portlet 模块Spring 的 Web 模块提供基本的以网络为中心的集成特性,例如文件上传,通过使用 Servlet 监听器初始化 IoC,面向 web 应用程序上下文。它还包含Spring 的远程支持的 web 部件。Web-Servlet 包含为 web 应用程序的 spring 的 MVC 实
9、现,spring MVC 框架将 web 表单和模型对象完全分离,并集成了 spring 框架的其他特性。Web-Portet 模块用于 portlet 环境和 Web-Servlet 模块的功能镜像的 MVC 实现。2.2.4 AOP 和工具Spring 的 AOP 模块提供了 AOP Alliance-compliant(AOP 兼容联盟)的一个面向切面编程的实现,并允许你自己定义,比如,方法拦截器和完全隔离代码的切入点(用于那些需要分离出来的功能实现) ,使用源码级别的元数据功能,你也可以在你的代码中加入行为信息,类似于.Net 属性设置。单独的 Aspects 模块提供了与 Aspec
10、tJ 的集成。工具模块提供了类工具的支持和应用于某些具体的应用程序服务器的类加载器实现。2.2.5 测试测试模块支持使用 Junit 或这 TestNG 来测试 Spring 组件。能够持续加载Spring 应用上下文,并对其进行缓存,同时也支持使用模拟对象的方式进行隔离测试你的代码。2.3 使用场景前面所提到的构建模块说明在很多场景下 Spring 都是一个合理的选择,从以 applets 为例的小应用程序到成熟的企业级应用程序都可以使用 Spring 的事务管理功能和 Web 框架的集成。Spring 的声明式事务管理特性使 web 应用程序完全事务化,就像使用 EJB容器管理的事务。你的
11、所有业务逻辑都可以通过简单 POJOs 实现并且托管于Spring 的 IoC 容器。其他的服务包括发送邮件和独立于网络层的验证规则,由此你可以选择验证规则作用于哪里。Spring 的 ORM 支持 JPA、Hibernate 和 JDO的集成;例如当使用 Hibernate 使,你可以继续使用你存在的映射文件和标准的 Hibernate 的 SessionFactory 配置。表单控制器将 web 层与领域模型层无缝集成,并且去除了 ActionForms 或者那些用于将 HTTP 参数转换为领域模型的值对象(VO )的类。在某些情况下不允许你完全地迁移到另一个框架。Spring 框架并没用
12、强迫你将其所用东西运用到你的项目中,它不是一个孤注一掷的解决方案。现有的基于 Struts、Tapestry、JSF 或者其他的 UI 框架的前端,可以集成一个基于 Spring的中间件,它允许你使用 Spring 事务功能。你只需要使用 ApplicationContext 和WebApplicationContext 组织你的业务逻辑从而集成到你的 Web 层。当你需要通过 web 服务访问现有的代码,你可以使用 Spring 的 Hessian-, Burlap-, Rmi- 或者 JaxRpcProxyFactory 类。远程服务的访问将不再是困难。Spring 框架也为企业级 Jav
13、aBeans 提供了一个访问和抽象层,使你能够重用已有的 POJOs,并且将他们包装在无状态的会话 Beans 中用于可伸缩的自动防故障的 web 应用程序,一般这些程序可能需要声明式的安全保障。2.3.1 依赖管理和命名约定依赖管理和依赖注入是不同的。为了获取 Spring 的优良特性(例如依赖注入) ,你需要收集所有需要的库(Jar 文件) ,并且在编译、运行的时候将它们放到你的类路径中。这些依赖不是被注入的虚拟组件,而是文件系统中的物理资源(通常情况下是这样的) 。依赖管理的过程包括定位那些资源,存储它们并将他们加入类路径。依赖的有直接(如我的程序在运行期依赖于 Spring)和间接(如
14、我的程序依赖于 commons-dbcp,而 commons-dbcp 有依赖于 commons-pool)这两种形式。间接的依赖也被称为“传递” ,它是最难识别和管理的依赖。如果你将要使用 Spring,你需要复制那些包含你需要的 Spring 功能的 jar 包。为了使这个过程简单,Spring 被打包成一组模块,这些模块尽可能的分开依赖关系。例如,如果不想写一个 web 应用程序,你就不需要引入 spring-web 模块。为了在本指南中标记 Spring 库模块我们使用了速记命名约定 spring-*或者spring-*.jar,其中*代表模块的短名(比如 spring-core,sp
15、ring-webmvc,spring-jms等) 。实际的 jar 包名,通常是用模块名字和版本号级联(如 spring-core-4.1.4.BULD-SNAPSHOT.jar) 。每一个发行版本将会被放到下面的位置: Maven Central(Maven 中央仓库) ,这是 Maven 查询的默认库,不需要任何特殊的配置就能使用。许多常用的 Spring 的依赖库也存在于 Maven Central,并且 Spring 社区的很大一部分都是用 Maven 进行依赖管理,所以这是最方便的,他们的 jar 命名格式是 spring-*-.jar,groupId是 org.springfram
16、ework。 公共 Maven 仓库还拥有 Spring 专有的库。除了最终的 GA 版本,还保存开发的快照版和里程碑版。JAR 文件的名字很 Maven Central 相同的形式,所以这是让 Spring 的开发版本使用其他部署在 Maven Central 库的一个有用的地方。该库还包含一个用于发布的 zip 文件,包含所有的 Spring jar 包方便下载。因此你的首要事是决定如何管理你的依赖:我们一般建议使用一个自动系统,就像 Maven,Gradle 或者 Ivy,当然你也可以通过下载自行管理。我们将在这一章节的后面部分进行详细的指导。Spring 依赖和依赖于 Spring尽管
17、 Spring 对于非常广泛的企业级业务和其他额外的工具提供了集成和支持,但是它力图将它的强制性依赖降到最低:你不必定位和下载(或者自动化获取)很大数量的 jar 库而仅仅只是为了在简单的场景中使用 Spirng。对于基本的依赖注入只需要一个外部的强制性依赖,并且只是用于日志(见下面关于日志的描述) 。接下来我们将一步一步介绍如何配置依赖 Spirng 的程序。首先是通过Maven,之后是 Gradle,最后是 Ivy。其中如果有任何不清楚的,可以参考你的依赖关系管理系统的相关文档,或者查看一些示例代码-Spring 本身是使用Gradle 来管理依赖的。并且我们的示例大多数也是使用 Grad
18、le 或 Maven。Maven 依赖管理如果你使用 Maven 的依赖管理,你甚至不需要明确提供日志依赖。例如,要创建一个应用程序的上下文和使用依赖注入来配置应用程序,你的 Maven 依赖将看起来像这样:如上图所示,注意 scope 节点可以被设置为 runtime 如果你不需要编译Spring APIs,这通常是基本的依赖注入的案例。以上是使用 Maven 中央仓库的使用示例。为了使用 Spring Maven 仓库(例如里程碑版或开发者快照版) ,你需要在你的 Maven 配置指定仓库位置。用于发布版:用于里程碑版:用于快照版:Maven “Bill Of Materials”依赖当使
19、用 Maven 时有可能不小心使用不同版本的 Spring 依赖。例如,你可能发现一个第三方库,或者另外一个 Spring 项目,使用了较早的发布版本的传递依赖。如果你忘记了显式声明一个直接依赖,各种问题将出现。为了克服这些问题,Maven 支持“Bill Of Materials”(BOM)的依赖概念。dependencyManagement 部分引入 spring-framework-bom 来确保所有 Spring 依赖(包括直接和间接依赖)是同一个版本。加入 BOM 的益处在于你不必再指定 属性,而此时 Spring framework 的依赖将是如下图所示:Gradle 依赖管理用
20、Gradle 使用 Spring,在 repositories 中填入适当的 URL:你可以让 repositories 的 URL 在/release、/milestone、/snapshot 之间切换,一旦指定 repositories,就可以通过一下方式声明依赖:Ivy 依赖管理如果你更喜欢 Ivy 管理依赖也有类似的配置选项。配置 Ivy,将指向 Spring 的库添加下面的解析器到你的 ivysettings.xml:你可以让 root 的 URL 在/release、/milestone、/snapshot 之间切换,一旦指定root,就可以通过一下方式声明依赖:分发 zip 文件
21、尽管使用构建系统管理依赖是推荐的方式,仍然可以下载分发的 zip 文件。分发的 zip 文件是发布到 Spring Maven 仓库(这是为了便利,在下载这些文件的时候你不需要 Maven 或其他构建系统) 。下载一个 zip,在 Web 浏览器打开http:/repo.spring.io/release/org/springframework/spring,选择适当的文件的版本。2.3.2 日志对于 Spring 日志是一个非常重要的依赖,原因有三点 :a)这是唯一的外部强制依赖,b)每位程序员都想查看使用的工具的输出,c)Spring 集成的所有工具都选择了日志依赖。开发者都有的一个目标通
22、常是希望在整个应用中有一个统一的日志配置,囊括了所有的外部组件。因为有如此多的日志框架使之相对较难实现。Spring 的强制日志依赖是 Jakarta Commons Logging API(JCL)。我们编译 JCL 同时也让 JCL 的 Log 对象对 Spring Framework 的扩展类可见。Spring 的所有版本都须使用相同的日志框架,这一点对于用户来说非常重要:迁移就会变得容易因为向后兼容性的保留,即使扩展 Spring 的应用程序。为达到此目的我们的做法是让 Spring 的其中一个模块显式地依赖 commons-logging(JCL 的规范实现) ,之后让其他所有的模块
23、都在编译期依赖该模块。假如你正在使用 Maven,并且想知道你在哪里使用了 commons-logging 依赖,答案就是来自于 Spring,确切的说是名为 spring-core 的中心模块。关于 commons-loggin 的好处在于你不需要任何东西就能让你应用程序跑起来。他有一个运行期的检索算法,它会在类路径下熟知的位置找到其他的日志框架,并使用一个它认为适合的日志框架(或者如果需要你可以告诉它该用哪个) 。如果没有一个可用的,那么你就可以获得一个来自于 JDK 的良好格式的日志(java.util.logging or JUL 的简称) 。大多数情况下,你可以在控制台查看你的 Sp
24、ring 应用程序工作和日志,这一点很重要。不使用 commons-logging不幸的是,common-logging 中为最终用户提供便利的运行期检索算法有问题。如果我们让时光倒流,重新开始一个使用了不同的日志框架的 Spring 项目。第一选择或许会是 Simple Logging Facade for Java(SLF4J) ,这个日志框架也被用于许多其他工具通过使用 Spring 应用到他们的应用程序中。关闭 commons-logging 很简单:只需要保证其在运行期不在类路径下就可以。就 Maven 而言你排除依赖就可以,因为 Spring 依赖声明的方式, 你只需要做一次。现在
25、这个应用程序可能出了点问题,因为在类路径下没有 JCL API 的实现。因此一个新的配置必须提供。在接下来的部分我们将为你展示如何提供一个可选的 JCL 实现,以 SLF4J 为例。使用 SLF4JSLF4J 是一个更加简洁的依赖,并且在运行期比 common-logging 更加高效,因为它是在编译期绑定而不是在运行期查找另外的日志框架与其集成。这也意味着你不得不更加清晰地了解在运行期你想要发生什么,并相应的声明或配置它。SLF4J 对很多通用的日志框架提供了绑定,因此你选择你以前使用过的框架,通过配置绑定到它并管理它。SLF4J 对很多通用的日志框架提供了绑定,包括 JCL,他也做了反响工
26、作:是其他日志框架与它自己的桥梁。因此在 Spring 中使用 SLF4J 你需要通过 SLF4J-JCL 桥接替代 common-logging 依赖。一旦你做了这些,在 Spring 中的日志调用将被转换为 SLF4J API 的调用,因此如果在你的应用中的其他库也使用了这个API,那么你就有一个唯一的地方来配置和管理日志。一个通常的选择是将 Spring 桥接到 SLF4J,之后提供从 SLF4J 到 Log4J 的显式桥接。你需要提供 4 各依赖(和排除存在的 common-logging 的依赖):桥接,SLF4J API ,Log4J 的绑定,Log4J 自身的实现。在 Maven
27、 中的配置如下图所示:这看起来好像仅仅为了一个日志就有了很多依赖。的确是这样的,但它也是可选的。它在关于类加载器的问题上应该比 commons-logging 表现的更加的好,值得注意的是,如果在一个严格的容器中,例如 OSGi 平台,据说这也是一个性能优势,因为绑定是在编译时而不是在运行时。在 SLF4J 的用户中还有一个更普遍的选择,那就是直接绑定到 Logback,它需要更少的步骤和更少的依赖。这种方式移除了额外的绑定步骤,因为 Logback是 SLF4J 的直接实现。因此你只需要依赖两个库( jcl-over-slf4j 和 Logback)而不是 4 个。如果你真想这么做,也许你需
28、要从其他的依赖(非 Spring)中移除slf4j-api 的依赖,因为你在类路径下只想使用一个版本的那种 API。使用 Log4J很多人为了配置和管理的目的从而使用 Log4J 作为日志框架。它是有效且完善的,事实上我们在构建和测试 Spring 时也是在运行期使用它的。 Spring 提供了一些方便配置和初始化 Log4J 的工具,因此在某些模块中它也是一个可选的编译期的 Log4J 依赖。为了让 Log4J 通过默认的 JCL(common-logging )依赖工作,你所需要做的就是将 Log4J 放在类路径下,并为其提供一个配置文件(在类路径的根路径下的 log4j.properti
29、es 或者 log4j.xml) 。针对 Maven 用户,依赖声明如下图所示:在控制台输出日志的 log4j.properties 文件示例:第二部分 Spring 4.X 的新特性3Spring4.0 的新特性和增强2004 年,Spring 最初版发布。自那以后最主要的几个版本包括:Spring2.0提供 XML 名称空间和 AspectJ 的支持;Spring2.5 增强了注解驱动的配置;Spring 3.0 引入了一个强大的 Java 5 +基础框架代码库,并且拥有诸如基于Configuration 的 Java 类配置模型的特性。4.0 是 Spring 框架的最新的主要发布版,首
30、次全面支持 Java8 特性。你仍然可以利用较低版本的 Java 来使用 Spring,当然,最低版本现在已经升级到 Java SE6。我们也利用本次主要版本的机会移除了一些被废弃的类和方法。升级到 Spring4.0 的指南在 Spring Framework GitHub Wiki(https:/ )上。3.1 改进的上手的经验最新的 Spring.io 网站(http:/spring.io/)提供了一整套“ 上手”指南让你学习Spring。你可以在那里了解到本文档第一部分的更详细内容。这个新网站还提供了一个全面的关于发布在 Spring 体系下的许多其他项目的概述。如果你是一个 Mave
31、n 使用者,你也许会对“bill of materials”的 POM 文件的益处感兴趣,现在该文件在每个 Spring 框架发布版都有。3.2 被移除的遗弃包和方法在 4.0 版中所有被遗弃的包和很多被遗弃的类和方法已经被移除了。如果你正在从旧版本 Spring 升级,你应该确保已经调整了过时 API 的调用。查看 API 异同报告(http:/docs.spring.io/spring-framework/docs/3.2.4.RELEASE_to_4.0.0.RELEASE/)获取完整的改变。请注意可选的第三方最低依赖也已经上升到 2011/2011(即 Spring4.0 只支持那些在 2010 年之后发布的版本):值得注意的是Hibernate3.6+,EhCache2.1+,Quartz1.8+,Groovy1.8+和 Joda-Time2.0+。