Spring
是一个开源的
J2EE
应用程序框架,其在轻量级
J2EE
开发中扮演着非常重要的角色。本章主要对
Spring
的作一个总体上的介绍,包括
Spring
是什么、
Spring
团队及
Spring
相关社区、
Spring
的功能体系、如何开始
Spring
等,本章最后还通过一个通俗、完整的
Spring
应用示例,演示了
Spring
在应用程序中所扮演的角色及作用,最后讲解了一些关于如何学好
Spring
的方法。
Spring
是什么?
Spring
能为我们做什么?为什么我们选择使用
Spring
?
Spring
由哪些功能部件组成?这是本节讲述的话题。
2.1.1
什么是
Spring
Spring
是
Rod
主创的一个应用于
J2EE
领域的轻量应用程序框架,其核心是一个
IOC
容器以及
AOP
实现,在核心上面的一个主要部件是数据访问
DAO
框架,包括一个自己的
JDBC
数据访问封装以及对众多
ORM
系统的集成支持。
Spring
还内置一个功能强大、灵活的
Web MVC
框架,以提供快速的
Java Web
应用程序开发,同时
Spring
还提供了以其它各种
MVC
框架或视图技术的集成。通过
Spring
的核心容器及
AOP
的应用,
Spring
提供了统一的声明式系统级服务支持。
Spring
的设计思想很多来源于
Rod Johnson
所写的《
Expert One-on-One J2EE Design and Development
》这本书。
Spring
项目在开源领域是一个非常活跃的项目,有着很多活跃的开源技术社区支持,在全世界范围内拥有不少的用户群体。
Spring
提供了众多优秀开源项目的集成,包括与各种优秀的
Web
框架集成,与优秀的开源持久层
ORM
系统集成,与动态语言的集成,与其它企业级应用的集成等。
可以这么说,由于
Spring
是主动去适应变化,去整合其他优秀的开源项目及技术,再加上
Spring
优秀的设计构架,其可扩展性非常强。所以
Spring
能很容易就把其它开源项目整合到其应用体系中,于是给我们看到的就是一个基于
Spring
核心体系,无所不能的
J2EE
应用程序框架。
2.1.2
Rod Johnson
、
Spring
团队及
Spring
交流社区
Rod Johnson
是
Spring Framework
的创建者,也是
Java
和
J2EE
领域中的知名专家。
Rod
是
Interface21
公司的
CEO
,该公司是一家致力于提供专业级
J2EE
和
Spring Framework
服务的咨询公司。谈到
Rod Johnson
,除了
Spring
框架本身以外,他所著作的《
Expert One-on-One J2EE Development without EJB
》一书,其影响力比
Spring
框架本身还更加震撼。
现在
Spring
团队已经成立了公司,除了提供商业咨询及顾问服务以外,公司还有几十个固定的工作人员在负责维护
Spring
项目,工作内容包括修改
Spring
中的
Bug
、为
Spring
增加新功能、解答
Spring
用户的问题等。相比其它一些开源项目,
Spring
的发布以及更新都非常活跃,能快速适应市场的变化。
Spring
在
2004
年初发布
1.0
版本,到
2006
年
10
月
3
日
发布了
2.0
版本,基本上维持着每半年就会有一次大的更新。
Spring
官方交流社区,
http://forum.springframework.org/
,官方网站提供非常活跃的技术交流,只要你提出一个问题,都会有很多大师级的人物迅速给予解答。作为商业上的支持,
Inteface21
公司专注于提供基于
Spring
技术框架的
J2EE
技术咨询服务,其官方网站为
, http://www.springframework.com/
或
http://www.interface21.com/
,当然
java
开源社区也有很多著名的网站提供
Spring
的技术交流,如
TSS(http://www.theserverside.com)
等。
2.1.3
Spring
能做什么
n
容器功能
Spring
的一个强大之处是他能代替
EJB
容器,负责管理用户基于
POJO
方式写的业务逻辑组件,具有类似
EJB
容器的功能,同时也是轻量级容器的代表。关于“轻量级容器”,我们将在下一章的“轻容器时代”一节详细讲述。
(POJO
,全称
Plain Old Java Objects
-简单的
Java
对象,实际就是普通
JavaBeans
,使用
POJO
的目的在于区别
EJB
,且简称比较直接,有一些属性及
getter setter
方法
!)
Spring
所管理的对象及组件,统一叫做
Bean
。跟其它的轻量级容器一样,
Spring
的容器除了最基本的贮存功能以外,同时也具有对象及组件创建
(Bean
工厂负责生产
Bean
)功能,还具有
Bean
之间的依赖及相关关系管理以及
Bean
生命周期管理的功能。也就是说,
Spring
负责管理
Bean
的创建、提供基于配置文件、声明式的
Bean
组装方式,自动管理
Bean
之间的相互依赖关系及
Bean
的生命周期。
另外,
Spring
核心容器还为基于
POJO
的
Bean
提供一些基础性的系统服务,通过引入
AOP
技术,实现了声明式的事务、安全、日志管理等功能。通过使用
AOP
,用户还能根据实际项目需要设计并实现自己的切面,解决横切交叉关注点中的问题。
n
黏合剂
/
组装功能
Spring
已经把很多优秀开源项目以一种非常优雅的方式集成在一起,同时
Spring
用户也可以把自己项目中开发的组件或框架非常方便的集成到
Spring
中,然后享受
Spring
核心容器提供的各种服务。在这里,
Spring
更多的扮演了黏合剂角色,他就像一个强力的黏合剂,以一种非常简单、统一的方式就能把各种各样、五花八门的组件、工具及项目等组合到一起,然后形成一个可交付的
J2EE
应用软件。因此,也可以说
Spring
具有组装功能,通过组装的方式来构建一个系统。
n
企业应用开发实用工具集
Spring
提供了很多轻量级应用开发实践的工具集合,这些工具集以接口、抽象类、或工具类的形式存在于
Spring
中。通过使用这些工具集,可以实现应用程序与各种开源技术及框架间的友好整合。比如有关
jdbc
封装的数据访问工具
Spring JDBC
,有关编写单元测试的
spring test
包以及
spring-mock
,有关访问动态脚本语言的
Spring Script
,另外还有发送邮件的工具
Spring Mail
、日程及任务处理工具
Spring scheduling
等。
可以这么说,大多数企业级应用开发中经常涉及到的一些通用的问题,都可以通过
Spring
提供的一些实用工具包轻松解决。
n
通用实践抽象
Spring
的开发者本身都有着非常丰富、涉及领域非常的广泛的
J2EE
应用开发经验。因此,框架内置了很多在实践中积累而来的通用问题的解决方案。比如,在
Spring
中,我们随处可以看到一种称为
Template
的机制,封装了很多实用的模板代码,然后以回调的形式让用户根据自己的实际情况完成个性化需求的代码填写,比如
Spring
中有关
jdbc
的封装、
DAO
的应用、访问
JNDI
资源、访问
EJB
、访问
Web Service
等。
总体来说,
Spring
有自己的表示层
MVC
框架,有自己的持久层数据访问工具,有自己的核心容器,可以灵活使用声明式系统级服务,还有很多实用的企业级应用开发中经常要用到的实用工具集及通用问题的解决方案,并且能与任何有用的
J2EE
或非
J2EE
技术集成。因此,可以这么说,如果你是一个
Spring
忠实爱好者,并了解
Spring
的各组成部分并能充分利用其提供的各种实用工具,完全可以把他作为企业应用开发的一整套解决方案。只有在需要的时候,引入
EJB
技术或
Web Service
技术来解决分布式应用问题,然后再集成到
Spring
中即可。
当然,
Spring
有一个很让人称道的理念:不把自己的世界观强加给用户!强调的是一种自由观念,用户可以自由选择自己熟悉的技术及框架开发自己的组件
(
不需要依赖于
Spring
的任何东西
)
,然后再把他们组合放到
Spring
中运行。
2.1.4
Spring
框架总体构架
下面我们通过引用
Spring
参考文档中的一些图,从而对
Spring
有一个总体上认识。首先来看一下
Spring
框架的总体结构图,如“图
2-1”
。我们从下往上看,最底层是
Spring
框架的核心
IOC
容器,也是
Spring
最基础的部分,
Spring
的其它功能大多都依赖于这个核心容器来支撑。紧接着
Spring
核心容器上是
Spring
的
AOP
层,
Spring
有自己单独的
AOP
实现,同时还集成了
AspectJ
的
AOP
功能。因为数据访问层都考虑了声明式事务处理等,因此在
AOP
层上面是
Spring
的数据访问层。数据访问层包括两大部分,
DAO
部分主要是
Spring
对
jdbc
的封装以及事务管理,
ORM
部分是
Spring
与其它各种轻持久层对象-关系映射框架的整合及集成,如
Hibernate
、
JPA
等。然后再往图的右边看有两大部分,
JEE
部分封装了企业级应用中的一些常用服务及功能,如
JMS
、
Email
、
EJB
、
Remoting
等;
WEB
部分主要是
Spring
自己的
MVC
实现以及与其它
MVC
框架(如
Struts
、
Tapestry
、
JSF
等
)
的综合集成等。
图
2-1
Spring
框架总体结构图
从上面的图可以看到,
Spring
提供了很多
J2EE
应用的基础设施及解决方案,便于我们开发
J2EE
应用,
Spring
是一个非常灵活、松散的框架。除了
J2EE
应用,还可以用于其它各种各样的场景。下面通过列举一些常用的应用程序场景,演示
Spring
如何在这些应用中发挥作用。
先来看一个完整
Spring MVC WEB
应用,如“图
2-2”
。通过使用
Spring
声明式事务管理,可以把事务声明及管理用于普通的
POJO
。最外层是
Spring
的
MVC
框架,中间是
Spring IOC
核心容器,即
Web
应用上下文。在容器中还有其它业务逻辑层组件,这些组件可以使用
Spring
的
DAO
访问数据或者使用
Spring
集成的第三方持久层框架(如
Hibernate
)进行数据访问。最底层仅仅只需要一个
Web
容器。
图
2-2
基于
Spring MVC
框架的完整
Web
应用
当然也可以只选择使用
Spring
的核心容器及
AOP
功能,表示层及持久层使用第三方的解决方案,此时一个基于
Spring
应用框架的
J2EE
应用如“图
2-3”
所示,最外层是
Web MVC
层,可以是
Struts
、
WebWork
或
EasyJWeb
等。业务逻辑层是普通的
POJO
,数据访问层使用其它
ORM
框架,业务逻辑层及数据访问层都可以使用
Spring
提供的声明式事务特性,主要由
Spring AOP
来负责,再往下看是
Spring
的核心容器,最后是
Web
容器。
图
2-3
基于第三方
MVC
框架的
Spring Web
应用
在一些更大型的企业级应用中,需要访问远程的服务,
Spring
同样能发挥作用。此时业务逻辑层通过
Spring
提供的远程访问包,可以轻松实现访问远端的服务,如“图
2-4”
。
图
2-4
Spring
的远程访问
2.2
开始
Spring
之旅
通过前面小节的介绍,已经对
Spring
有一个总体的认识。然而我们从哪儿得到
Spring
?如何开始一个
Spring
的应用项目实践?如何在项目中使用
Spring
?在本节中,将通过图文结合的方式,讲解
Spring
的下载、安装及使用。
2.2.1
获取
Spring
首先到
Spring
官方网站下载
Spring
,网址是
http://www.springframework.org/
,点击
【
download
】
栏目,进入下载页面,如“图
2-5”。
图
2-5 Spring
官方网站
然后点击需要下载的
Spring
版本,作为研究我们推荐尽量选择最新的版本,如当前的
Spring Framework 2.0
,即可进入
www.sourceforge.net
中下载
Spring
的源代码,如“图
2-6”。
图
2-6
SourceForge
上
Spring
下载连接
(
备注:
SourceForge
是全球最大的开放源代码软件开发平台和仓库,它集成了很多开放源代码应用程序,为软件开发提供了整套生命周期服务。
SourceForge.net
是开放源代码软件的开发者进行开发管理的集中式场所,也是源代码仓库。
)
通过点击
SourceForge
中
Spring
项目相应的连接,即可开始下载
Spring2.0
的整个项目源码,如“图
2-7”
:
图
2-7 Spring
项目下载服务器选择
2.2.2
Spring
项目文件简介
下载完后,得到一个类似
spring-framework-2.0-xxx.zip
的压缩包,然后我们解压该压缩文件,即可见到
Spring
的项目文件,如“图
2-8”
。
图
2-8 Spring
项目文件
n
根目录
在根目录上,主要是
Spring
开源项目的
ant
脚本文件
build.xml
,
maven
脚本
maven.xml
等。我们可以在命令行输入
ant tests
来运行
Spring
的所有测试代码,另外还可以使用
ant build
及
ant alljars
实现在本机上根据自己的
jdk
重新编译
Spring
、并生成相关的
jar
包。
在根目录上,还有
spring
的发布协议说明
license.txt
、项目说明
readme.txt
、变更日志
changelog.txt
、注意事项
notice.txt
等文件。
n
dist
目录
在
Spring
项目的文件中,
dist
是已经编译打包好的发布
jar
,
dist
中的文件结构如“图
2-9”
所示:
图
2-9 dist
文件目录中的内容
其中
spring-src.zip
是
Spring
源码的压缩包,
spring.jar
是整个
Spring
源代码经过编译后的打包文件,
spring-mock.jar
是
spring
提供用于单元测试中模仿对象的相关类,
spring-aspects.jar
是
spring
与
aspectj
的集成的
jar
包。
Resources
目录是
spring
项目的相关资源文件,如配置文件描述符
spring-beans.dtd
等。
dist
中的
modules
目录是
spring
各组成部分单独发布的
jar
包。因为
Spring
的各组成部分是完全独立的,用户可以只选择使用
Spring
中的一部分功能,此时可以只直接使用相关部分
jar
文件即可。比如只用
spring mvc
就选择
spring-webmvc.jar
,要用
Srping
中的
jdbc
封装可以直接选择
spring-jdbc.jar
,
modules
目录中的内容如“图
2-10”
所示。
图
2-10 modules
目录中的内容
n
docs
目录
docs
目录是
Spring
项目的文档目录,里面主要包括
Spring
项目使用说明文档及系统
API
等,在
Spring2.0
的项目中,包括
api
文档、
spring mvc
应用简单示例、
spring
参考手册、
spring
标签库简介等几个部分,如“图
2-11”。
图
2-11 docs
目录中的内容
n
mock
目录
mock
目录是
Spring
用于单元测试中模仿对象的
mock
实现源代码,也就是
spring-mock.jar
中的源码。
n
aspectj
目录
aspectj
目录是
Spring
与
AspectJ
集成的源代码及应用测试代码。
n
src
目录
src
目录是
Spring
项目的全部源代码。
n
samples
目录
samples
目录是
Spring
项目的应用程序示例源代码,主要包括一个简单的网上商店
jpetstore
,一个宠物医院
petclinic
。另外还有演示一些特殊功能的简单示例,如
countries
、
imagedb
等。通过这些示例程序代码,可以快速学习到
Spring
使用方法。
n
test
目录
test
目录是
Spring
项目的单元测试代码,
Spring
作为测试驱动开发的推崇者,有着非常详细的单元测试用例,通过单元测试代码,可以快速掌握
Spring
各个类的方法。
n
tiger
目录
tiger
是
Spring
项目中使用
java tiger
版中的新功能及特性的源代码,包括注解等。
n
lib
目录
lib
目录中包括了
Spring
项目用到的所有
jar
文件,
Spring
一个特点就是提供了对很多主流框架的集成支持,很多功能是在一些现存的项目上搭建起来的。因此,要使用这些特性,必须在项目中引入相关的
jar
。在
Spring
的
lib
目录中,这些
jar
文件分门别类的存放于
lib
的子目录中,如“图
2-12”所示。
图
2-12 lib
目录中的内容
2.2.3
查看
Spring
源码
由于
Spring
的功能相当强大,其源代码的数据以及源代码的层次结构等都相当复杂,因此需要借助专业的
Java
开发工具,来查看
Spring
的项目源码。
Spring2.0
的源代码需要在
Jdk1.5
以上的版本才能全部正常编译。下面演示在
Eclipse
中如何打开
Spring
的源代码:
第一步,在
Eclipse
新建一个工程,在
【
新建工程
】
对话框中,选择
【
create project from existing source
】
,然后通过浏览文件对话框选择
Spring
项目的主目录,如“图
2-13”
所示。
图
2-13
选择
Spring
项目目录
第二步,选择好
Spring
项目的目录后,点击
【
next
】
按钮,
Eclipse
会加载
Spring
项目文件,进入项目的
setting
配置对象框。该对话框中我们主要检查
Source
(源代码目录)及
Libraries(
相关
jar
包
)
两个部分,分别如“图
2-14”及“
图
2-15”
所示。
图
2-14
Spring
项目的源码路径
图
2-15
Spring
项目所需要的
jar
库文件
第三步,点击
【
完成
finish
】
按钮,完成项目的创建,这里即可通过在
Eclipse
的
【
package explorer
】
视图面板中查看到
Spring
项目的源代码,如“图
2-16”
所示。
图
2-16 Spring
项目源码总体结构
2.2.4
使用
Spring
要在项目中使用
Spring
,需要把
Spring
编译打包后的
jar
文件引入到项目的
Classpath
中。通过直接使用
Spring
的相关
jar
包,开始使用
Spring
。下面演示使用
Eclipse
开发一个简单的
Spring
示例程序。
第一步,使用
Eclipse
的
【
new project
】
向导,新建一个名为
spring-hello
的工程。
第二步,新建一个名为
Hello
的类,
package
选择
com.easyjf
,如“图
2-17”
所示。
图
2-17
新建项目
第三步,
把所需要使用的
Spring
项目
jar
的文件加入到当前工程的
Libraries
中,本例中只使用
Spring
的简单
IOC
功能,只需要
spring-beans.jar
、
spring-core.jar
以及
commons-logging.jar
三个包即可。
右键点击工程名称,查看工程属性,选择工程属性中的
【
Java Builder Path
】
,然后选择
【
Libraries
】
选项,通过点击
【
add external jar
】
按钮来把外部的
jar
文件添加到工程项目中。
如下图所示:
图
2-18
把
jar
添到构建路径
第四步,
录入
Hello.java
的完整源代码,其中
Hello
这个类有一个
msg
属性,有一个
setMsg
方法用于设置
msg
属性的值。另外,我们直接在
Hello
的
main
方法中使用
Spring
的
Bean
工厂来从配置文件中加载一个名为
helloBean
,类型为
com.easyjf.Hello
的
Bean
。然后调用这个
Bean
的
sayHello
方法。全部源代码如下所示:
package com.easyjf;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class Hello {
private String msg;
public void setMsg(String msg)
{
this.msg=msg;
}
public void sayHello()
{
System.out.print(msg);
}
public static void main(String[] args) {
Resource res=new ClassPathResource("com/easyjf/bean.xml");
BeanFactory factory=new XmlBeanFactory(res);
Hello hello=(Hello)factory.getBean("helloBean");
hello.sayHello();
}
}
第五步
,在与
Hello.java
同级的目录下,建一个名为
bean.xml
的
Spring
配置文件,在这个
Bean
配置文件中定义
helloBean
,并通过依赖注入设置
helloBean
的
msg
属性值,其内容如下:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!
DOCTYPE
beans
PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<
beans
>
<
bean
id
=
"helloBean"
class
=
"com.easyjf.Hello"
>
<
property
name
=
"msg"
value
=
"
这是最简单的
Spring
示例
!"
/>
</
bean
>
</
beans
>
完成后的工程项目如“图
2-19”
所示。
图
2-19
Hello
项目结构图
第六步,
运行程序,在
Hello.java
上点右键,选择
【
Run As
】
下面的
【
Java Application
】
。即可运行这个使用了
Spring
的程序,该程序将输出
helloBean
中的
msg
属性的值:“这是最简单的
Spring
示例
!
”,如“图
2-20”所示。
图
2-20
Spring
版的
Hello
程序输出结果
到这里为止,我们就完成了一个最简单的
Spring
应用实践。
这个例子我们使用了
Spring
的
IOC
功能。具体来说就是通过一个资源文件
(Resource) res
,创建一个
Bean
工厂实例
factory
,然后再通过
factory
来查找程序中需要使用的
Bean
,最后使用具体的
Bean
完成相应的工作。
当然,这个示例说明不了多少问题,没有展示出
Spring
的特长。下一节我们将通过一个组装电脑的示例来演示
Spring IOC
的强大功能。
2.3
示例:用
Spring
来组装电脑
在上一节,我们学习了怎样在自己的项目中使用
Spring
,并通过一个
Spring
版本的
Hello
程序演示了
Spring IOC
的功能。在这一节,我们将通过一个通俗完整的
OOP
应用示例,演示
Spring
在构建松散耦合的系统过程中的作用及功能。
2.3.1
示例简介
大多数搞软件的朋友,都有组装电脑的经历,选择什么样的主板、硬盘、
CPU
、显示器都是值得仔细研究的,要考虑价格、要考虑款式、或者是商家的售后服务质量等等很多因素。今天这里不是讨论怎么组装电脑,而是想通过组装电脑的示例,演示一下
Spring
通过灵活的组装
Bean
,像搭积木一样堆积成一个能实现客户所需功能的软件。
我们知道,一台电脑由主板、硬盘、
CPU
及其它输入输出设备等组成,只有电脑的各个组成部分都能运行,电脑才能正常工作。而在企业级的应用软件中,很多时候我们会有很多的对象,这些对象之间有一定的关系,有些对象需要在其它对象都正常的情况下才能工作,把这些结构关联的类有机地组织到一切,就形成一个可用的组件。
下面我们以电脑这个实体为例子,演示使用
Spring
来灵活组装一台电脑,然后把一个完整的电脑提供给客户使用。
2.3.2
定义
Bean
-
定义电脑的组成配件并实现电脑的设计
在这个示例中,我们假设每台电脑由内存、主板、
CPU
三个基本的电脑元件组成,内存及
CPU
需要插在主板上才能工作。我们假定有各式各样的主板、内存及
CPU
可供选择,因此可通过
Java
接口来抽象各配件的定义。下面我们先来做关于各个配件的接口设计。
首先是电脑配件最基本的接口
PCComponent
,该接口的
UML
如“图
2-21”
所示:
图
2-21 PCComponent
类图
其代码如下:
package springroad.deomo.chap2;
public interface PCComponent {
String getName();//
名称
double getPrice();//
价格
String getCompany();//
厂家
}
CPU
接口表示所有
CPU
的抽象,
CPU
接口的
UML
如“图
2-22”
所示:
图
2-22 CPU
类图
其代码如下:
package springroad.deomo.chap2;
public interface CPU extends PCComponent{
int getSpeed();//
处理器速度
void doInstr(); //
做指令运算
void outResult();//
输出结果
}
Ram
接口表示所有内存的抽象,该接口的
UML
如“图
2-23”
所示:
图
2-23 Ram
类图
其代码如下:
package springroad.deomo.chap2;
public interface Ram extends PCComponent{
int getSize();//
内存大小
void inData();//
读数据
void outData();//
取数据
}
Mainboard
接口表示所有主板的抽象,该接口的
UML
如“图
2-24”
所示:
图
2-24 Mainboard
类图
Mainboard
接口的代码如下所示:
package springroad.deomo.chap2;
public interface Mainboard extends PCComponent {
void setCpu(CPU cpu);//
安装
cpu
CPU getCpu();//
得到主板上的
CPU
void setRam(Ram ram);//
安装内存
Ram getRam();//
得到主板上的内存
boolean havePower();//
是否有电源
void startPower();//
开电源
void shutdownPower();//
关电源
}
完成了电脑各组成部分的定义后,就可以来开始实现电脑
Computer
类的设计了。在这个示例中,我们假设电脑主要由一个主板
mainboard
组成,电脑有开机
start
、关机
shutdown
以及工作
doWork
等动作,另外还可以通过
getSetting
及
getPrice
等方法返回电脑的配置及价格信息。
Computer
的
UML
类图如“图
2-25”
所示:
图
2-25 Computer
类图
下面是
Computer
类的全部代码:
package springroad.deomo.chap2;
public class Computer {
private Mainboard mainboard;//
主板
//
电脑的显示器、鼠标键等其它属性省略
public void setMainboard(Mainboard mainboard) {
this.mainboard = mainboard;
}
public void doWork()
{
System.out.println("
开始工作
...");
for(int i=0;i<100;i++)
System.out.print(i+" ");
System.out.println("
结束工作
!");
}
public void start()
{
mainboard.startPower();
}
public void shutdown()
{
mainboard.shutdownPower();
}
public double getPrice()
{
return mainboard.getPrice()+mainboard.getCpu().getPrice()+mainboard.getRam().getPrice();
}
public String getSetting()//
读取电脑配置信息以及价格总额
{
String ret;
ret="
电脑组成如下
!
主板
:"+mainboard.getName()+"
,
CPU:"+mainboard.getCpu().getName()+"
,内存
:"+mainboard.getRam().getName()+"\n";
ret+="
这个配置的价格为:
"+getPrice();
return ret;
}
}
“图
2-26”
显示了这个示例设计的总体
UML
结构图,图中的
AbstractMainboard
表示主板的抽象,将在后面讲解。
图
2-26
装机示例的
UML
结构图
2.3.3
实现
Bean
-
提供可供选择的配件
在上面的配件设计及
Computer
类中相关的业务逻辑代码中,还缺少具体的主板、
CPU
以及内存实现,由于每种配件可选择的类别很多,不同厂家生产的配件除了一些标准定义的共性以外,还有自己的特性。因此,光有接口就类似于只有一个配件接口标准
(
一个空壳的电脑
)
,
Computer
是无法工作的,下面需要分别提供主板、
CPU
及内存的实现。作为惯例,我们把实现写在
impl
包下面。
(1)
、提供可供选择的具体主板
Mainboard
下面我们先来看主板
Mainboard
的实现。虽然主板
Mainboard
有多种多样,但其一些业务逻辑是差不多的。因此,我们先通过一个抽象类
AbstractMainboard
来定义主板
Mainboard
的一些共同的业务逻辑,然后再让具体的主板类继承该抽象类即可,
Mainboard
接口下的相关类的
UML
如“图
2-27”
所示:
图
2-27
主板实现的类图
下面是
AbstractMainboard
的全部代码:
package springroad.deomo.chap3.impl;
import springroad.deomo.chap2.CPU;
import springroad.deomo.chap2.Mainboard;
import springroad.deomo.chap2.Ram;
public abstract class AbstractMainboard implements Mainboard {
private CPU cpu;
private Ram ram;
private boolean power;
public void setCpu(CPU cpu) {
this.cpu=cpu;
}
public CPU getCpu() {
return cpu;
}
public void setRam(Ram ram) {
this.ram=ram;
}
public Ram getRam() {
return ram;
}
public boolean havePower() {
// TODO Auto-generated method stub
return power;
}
public void startPower() {
power=true;
}
public void shutdownPower() {
power=false;
}
}
通过继承主板抽象类,我们提供两种可供选择的主板,即
AUSU
生产的主板以及
Intel
生产的主板。其中
AUSUBoard
类的代码如下:
package springroad.deomo.chap2.impl;
public class AUSUBoard extends AbstractMainboard {
public String getName() {
return "AUSU
主板
";
}
public double getPrice() {
return 3000.00;
}
public String getCompany() {
return "SUSU
公司
";
}
}
IntelBoard
类的代码如下:
package springroad.deomo.chap2.impl;
public class IntelBoard extends AbstractMainboard {
public String getName() {
return "Intel
主板
";
}
public double getPrice() {
return 3500.00;
}
public String getCompany() {
return "Intel
公司
";
}
}
(2)
、提供具体可供选择的
CPU
实现
在本示例中,我们暂时只提供两款可供选择的
CPU
,分别是
Intel
的
CPU
,以及
AMD
的
CPU
。
UML
结构如“图
2-28”
所示:
图
2-28 CPU
实现的类图
IntelCPU
类的代码如下:
package springroad.deomo.chap2.impl;
import springroad.deomo.chap2.CPU;
public class IntelCPU implements CPU {
public int getSpeed() {
return 1700;
}
public void doInstr() {
System.out.println("
做指令运算
");
}
public void outResult() {
}
public String getName() {
return "IntelCPU";
}
public double getPrice() {
return 2500;
}
public String getCompany() {
return "Intel
公司
";
}
}
AMDCpu
类的代码如下:
package springroad.deomo.chap2.impl;
import springroad.deomo.chap2.CPU;
public class AMDCpu implements CPU {
public int getSpeed() {
return 1500;
}
public void doInstr() {
System.out.println("
做指令运算
");
}
public void outResult() {
}
public String getName() {
return "AMD CPU";
}
public double getPrice() {
return 1800;
}
public String getCompany() {
return "AMD
公司
";
}
}
(3)
、提供可供选择的具体的内存
Ram
实现
作为演示,本例我们也只提供两款可供选择的内存。分别是
Kingmax
的内存,以及
Kingstone
的内存。
Ram
相关类的
UML
如“图
2-29”
所示:
图
2-29 Ram
实现的类别
其中
KingmaxRam
类的代码如下:
package springroad.deomo.chap2.impl;
import springroad.deomo.chap2.Ram;
public class KingmaxRam implements Ram {
public int getSize() {
return 512;
}
public void inData() {
//
读入数据
}
public void outData() {
//
输出数据
}
public String getName() {
return "Kingmax
内存
";
}
public double getPrice() {
return 300;
}
public String getCompany() {
return "Kingmax
公司
";
}
}
KingstoneRam
类的代码如下:
package springroad.deomo.chap3.impl;
import springroad.deomo.chap3.Ram;
public class KingstoneRam implements Ram {
public int getSize() {
return 512;
}
public void inData() {
//
读入数据
}
public void outData() {
//
输出数据
}
public String getName() {
return "Kingstone
内存
";
}
public double getPrice() {
return 200;
}
public String getCompany() {
return "Kingstone
公司
";
}
}
这样,我们已经有了具体的
Computer
类,有了各个具体的配件实现。接下来要做的就是,根据用户的喜好,选择相关的配件组装到电脑里面,从而形成一个可以工作的电脑。
2.3.4
配置
Bean
-
组装电脑
下面在
springroad.deomo.chap3
这个包下面建设一个
Spring
的
Bean
配置文件,我们随便取一个名字,这里为
computer-bean.xml
。配置文件中的内容如下:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!
DOCTYPE
beans
PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<
beans
>
<
bean
id
=
"myMainboard"
class
=
"springroad.demo.chap2.impl.IntelBoard"
>
<
property
name
=
"ram"
><
bean
class
=
"springroad.demo.chap2.impl.KingmaxRam"
/></
property
>
<
property
name
=
"cpu"
><
bean
class
=
"springroad.demo.chap2.impl.IntelCPU"
/></
property
>
</
bean
>
<
bean
id
=
"myComputer"
class
=
"springroad.demo.chap2.Computer"
>
<
property
name
=
"mainboard"
ref
=
"myMainboard"
/>
</
bean
>
</
beans
>
在配置文件中,通过
<bean>
标签来定义了一个
id
为
myMainboard
的主板,一个
id
为
myComputer
的电脑。通过
<bean>
标签下的
<
property
>
分别设置了主板上选择的具体的内存
Ram
及
CPU
,另外还通过
myComputer
的
<
property
>
标签设置了
mainboard
属性为
myMainboard
。
2.3.5
应用
Bean
-
使用电脑
下面,写一个简单的客户端程序来运用
Computer
对象,做一些简单的工作。我们在
springroad.deomo.chap3
包下添加一个名为
ClientDemo
的带有
main
方法程序,
ClientDemo
的全部代码如下:
package springroad.deomo.chap2;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class ClientDemo {
public static void main(String[] args) {
//
定义
Spring Bean
工厂资源文件
Resource res=new ClassPathResource("springroad/demo/chap2/computer-beans.xml");
//
创建一个
Bean
工厂
BeanFactory factory=new XmlBeanFactory(res);
//
从
Bean
工厂中取出一个名为
myComputer
的
Computer
对象
Computer computer=(Computer)factory.getBean("myComputer");
//
执行
computer
的
doWork
方法,使得
commputer
开始工作
computer.doWork();
//
输出电脑的配置信息
System.out.println(computer.getSetting());
}
}
此时通过
Eclipse
环境直接可以运行这个
ClientDemo
程序,在
ClientDemo
上点右键选择
Run As
,然后点
Java Application
,程序成功运行会在输出面板中得到如下图所示的结果:
下面,我们简单的修改一下
computer-bean.xml
文件中的内容,把
myMainboard
中的
cpu
的属性值改为
springroad.deomo.chap3.impl. AMDCpu
,表示这个电脑使用
AMD
的
CPU
。
然后运行
ClientDemo
程序,我们会看到电脑的
Computer
的配置信息及总价格已经有了改变,如“图
2-30”
所示:
图
2-30
装示例运行结果
当然,你还可以在配置文件中把
IntelBoard
换成
AUSUBoard
主板,把
KingmaxRam
内存换成
KingstoneRam
,都可以配出完整的电脑。
2.3.6
发布
Bean-
把电脑交给客户
作为一个可以自由工作的组件,应该要脱离具体的开发环境,我们最终交给用户的应该是一个打包好的可以正常运行的程序。也相当于我们电脑组装人员要把组装好的电脑交给客户使用。
下面我们使用
Eclipse
把这个示例打包成
jar
发布,使用
Eclipse
的
Jar Export
可以简单实现该功能,如“图
2-31”
所示。
图
2-31
打包
computer
组件
假设我们发布的
jar
文件名为
computer.jar
,然后即可进入
dos
命令行,使用
java
命令执行刚才的程序,
(
注意,
computer.jar
、
spring.jar
及
commons-logging.jar
等文件所在路径
)
,执行方法如下:
java -cp computer.jar;lib/spring.jar;lib/commons-logging.jar;. springroad.deomo.chap2.ClientDemo
则可以看到如“图
2-32”
所示的结果:
图
2-32
在命令运行客户端应用的输出
可以直接使用解压工具如
winzip
或
winrar
等打开
computer.jar
,如“图
2-33”。
图
2-33
用
WinRar
打开发布的压缩包
然后双击其中的
computer-bean.xml
文件,可以打开编辑器修改这个
Spring
配置文件的内容,比如我们在
xml
文本编辑器中把
computer-bean.xml
文件的内容改成如“图
2-34”
所示的内容。
图
2-34
在文本编辑器中修改配置文件
把修改的内容保存并覆盖
jar
中的内容后,此时,重新在
dos
命令窗口中执行刚才的命令,则会得到如“图
2-35”
所示的完全不同的配置结果。
图
2-35
修改配置文件后运行客户端程序的输出
由此,可以看到,通过使用
Spring
的
Bean
工厂,我们可以不需要改一句
Java
源代码,只需根据自己喜爱修改
Spring
的配置文件,即可配置一台完整的、可应用的电脑供客户端使用。
而且电脑组装人员在组装电脑、尝试各种配置的过程中,也只需要修改配置文件即可看组装的效果,而不需要修改程序代码。
2.3.7
传统的组装
为了作比较,我们来看看若是采用传统的方式,客户端程序应该怎样来组装一台可用的电脑。
ClientOldDemo
类是一个演示采用传统方式使用
Computer
的客户端示例,
ClientOldDemo
的全部源代码如下:
package springroad.deomo.chap2;
import springroad.deomo.chap2.impl.IntelBoard;
import springroad.deomo.chap2.impl.IntelCPU;
import springroad.deomo.chap2.impl.KingmaxRam;
public class ClientOldDemo {
public static void main(String[] args) {
CPU cpu=new IntelCPU();
Ram ram=new KingmaxRam();
Mainboard myMainboard=new IntelBoard();
myMainboard.setCpu(cpu);
myMainboard.setRam(ram);
Computer computer=new Computer();
computer.setMainboard(myMainboard);
//
执行
computer
的
doWork
方法,使得
commputer
开始工作
computer.doWork();
//
输出电脑的配置信息
System.out.println(computer.getSetting());
}
}
通过上面的程序可以看出,用户为了使用这个电脑工作,需要自己从
CPU
、
Ram
及
Mainboard
开始,一层一层地自己创建,然后把
CPU
及
Ram
装到主板上,然后再把主板装到
Computer
上,最后才能使用一个完整的、可以工作的电脑来执行相关的工作。若客端要换一种配置,则每换一样都需要修改程序中创建
Computer
各组成部分的代码,然后再编译、调试、打包、发布
!
2.3.8
示例角色浅析
本例中,
ClientDemo
相当于电脑的最终使用者,一个不会组装电脑的用户,其甚至不知道电脑由哪些部件组成,他需要的仅仅是一个完整可以正常工作的电脑;而负责维护
Spring
配置文件者,相当于组装电脑的一般技术人员,他不需要很高深的技术,不需要知道怎么样生产一块主板、生产一块
CPU
,只需要知道什么是主板,什么是
CPU
,什么是
Ram
,并且知道
CPU
及
Ram
应该插放在什么位置,知道主板怎么安装即可。而实现
CPU
接口、
Mainboard
接口及
Ram
内存的类编写人员,如编写
InterCPU
这个类的人员,就相当
CPU
厂家的一线专业技术工程师,他们需要对微电子、数据电路等很多非常专业的技术,他们需要对
CPU
的工作原理等非常了解。
电脑终端用户、组装人员、生产厂商的工程师三者之间形成了如“图
2-36”
所示的角色结构:
图
2-36
装机示例中的角色
如果是采用传统组装电脑的方式,比如
ClientOldDemo
中示例,则要求客户端用户必须了解具体的电脑组成部件
(
在
ClientOldDemo
中,用户不但要与
Computer
类打交道,还要与
CPU
、
Ram
等接口打交道
)
,知道每一个部件的生产方式
(ClientOldDemo
中用户知道使用
new
方法跟一个
CPU
实现类的类名来创建一个
CPU
实例
)
,并要清楚每一个部件之间的关系
(ClientOldDemo
中用户需要知道通过
setCpu
及
setMainboard
等方法把相关部件分别设置到主板及电脑对象中
)
,然后使用专业的电脑组装工具
(
修改源码及编译等
)
才能组装出一台可用的代码。
2.4
分享
Spring
学习方法
通过使用
Spring
,我们可以快速搭建轻量级的
J2EE
企业及应用平台。
Spring
是一个应用程序框架,更像一个强大的二次开发工具包。作为一个开源项目,
Spring
为我们了很多优秀的设计思想,融合了很多经典模式的应用。即使我们项目中不用
Spring
,也有必要对
Spring
从体系结构上有一定的了解,并深入了解他一些模块的设计方法。当然,若您的项目中需要用到
Spring
,则有必要学会选择一些适合自己的高效学习方法。下面是我们在学习使用
Spring
过程中的一些经验,供大家参考:
1、
安装并运行
Spring
项目中所附带的
example
示例。然后使用
Eclipse
等开发工具,了解这些项目的包结构,并认真阅读并理解一些重要示例的源代码。
2、
下载并运行一些优秀的开源示例应用代码,比如
Appfuse
。
3、
认真阅读
Spring
的参考文档,文档虽然是英文的,但我想只要你不放弃,通过应用一些即时翻译工具软件
(
如金山词霸
)
的帮助,可以帮助您的阅读。
4、
认真阅读
Spring
项目自带的单元测试代码,单元测试代码中的测试用例是我们了解一个类如何工作最好文档。
5、
阅读
Spring
项目中一些核心包,比如
core
、
bean
、
aop
、
context
等源代码,必要时,使用
UML
工具,绘制出这些代码的
UML
结构图,掌握各个接口、类之间的关系。
6、
多做项目练习及实践,理论上
Spring
可以组装任何项目,因此,可以试着把自己以前一些小项目,改成使用
Spring
的方式来组装。
7、
经常到一些国内外知名
Java
社区,加入一些
Spring
用户群等,做到随时能接触
Spring
的一手信息。
本章简单介绍了
Spring
项目的情况,并对其用途作了一些简单的归纳总结。另外,通过图文并茂的方式,演示如何下载、安装并运行一个简单的示例程序
hello
。本章中,我们重点举了一个组装电脑的例子,演示了
Spring IOC
的运用,并通过与传统的电脑组装方式,结合现实中的角色分工,展示了
Spring
带给我们一些奇妙功能及特性。
本章只是
Spring
的入门章节,主要让新手能了解
Spring
,轻松把
Spring
运用起来。若你是新手,可以确保自己独立根据本章示例的操作步骤,完成本章中的两个实例后,再继续以后的章节;若您曾经使用过
Spring
,则请直接通过下面其它章节,具体了解
Spring
的一些使用方法及技巧。当然,若您已经很熟悉
Spring
应用的老手,则可以直接跳到本书的第二及第三部分内容。
请想想能不能用一种方式,不需要使用
Spring
,同时也不需要修改及重新编译源代码,通过配置文件就能实现自由灵活的电脑组装。