第6章 初始Spring框架
了解Spring框架的概念和优点
理解Spring框架中的IoC和DI思想
掌握ApplicationContext容器的使用
掌握属性setter方法注入的实现
本章简介
前面学习了MyBatis框架,了解了Java持久化框架的基本知识。
从本章开始学习一个非常著名的轻量级企业级开源框架—Spring,它不仅能构建规范,优秀的应用程序,还能简化繁琐的编码过程,Spring框架已经发展成为一个功能丰富且易用的集成框架,其核心是一个完整的基于控制反转(Ioc)的轻量级容器,用户可以使用它建立自己的应用程序。
Spring提供了大量实用的服务,将很多高质量的开源项目集成到统一的框架中。
本章将带领大家初步接触Spring框架的两个核心概念——IoC和AOP,感受Spring框架的神奇魅力。
技术内容
Spring框架是当前主流的Java Web开发框架,它是为了解决企业应用开发复杂性的问题而产生的。
对于提供Java开发人员来说,掌握Spring框架的使用已是必备的技能之一。
下面将对Spring框架的基础知识进行详细讲解。
6.1 Spring框架概述
6.1.1 企业级应用开发
在学习Spring框架前,首先了解一下企业级应用。
企业级应用是指那些为商业组织,大型企业而创建并部署的解决方案及应用。
这些大型企业级应用的结构复杂,涉及的外部资源众多事务密集,数据规模大,用户数量多,有较高的安全性考虑和较高的性能要求。
当代的企业级应用并不是一个个独立的系统,一般都会部署多个进行交互的应用,同时这些应用又都有可能与其他企业相关应用连接,从而构成一个结构复杂的,跨越Internet的分布式企业应用的集群。
此外,作为企业级应用,不但要有强大的功能,还要能够满足未来业务需求的变化,即易于扩展和维护。
传统Java EE解决企业级应用问题时的“重量级”架构体系,使它的开发效率,开发难道和实际的性能都令人失望。
正在人们苦苦寻找解决办法的时候,Spring框架以一个“救世主”的形象出现在广大Java程序员面向。
说到Spring框架就得提到它的作者Rod Johnson,2002年他出版了《Expert One-on-One Jave EE设计与开发》,在书中,他对传统的Java EE技术日益臃肿和低效提出了质疑,他觉得应该有更便捷的做法,于是提出了Interface21,也就是Spring框架的雏形。
他提出了技术以实用为准的主张,引发了人们对“正统” JavaEE的反思。
2003年2月,Spring框架正式成为一个开源项目,并发布于SourceForg中。
Spring框架是由Rod Johnson组织和开发的一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,它以IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为内核,使用基本的JavaBean来完成以前只可能由EJB(Enterprise Java Beans)完成的工作,取代了EJB的臃肿,低效的开发模式。
Spring框架致力于Java EE应用的各种解决方案,而不是仅仅专注于某一层的方案。
可以说,Spring框架是企业应用开发的“一站式”选择,Spring框架贯彻表现层,业务逻辑层和持久层。
在表现层提供了框架Spring MVC与Struts的整合功能;
在业务逻辑层可以管理事务,记录日志等;
在持久层可以整合框架MyBatis,Hiberbates JdbcTemplate等技术。
因此,可以说Spring框架是企业应用开发很好的“一站式”选择。
虽然Spring框架贯彻与表现层,业务逻辑层和持久层,但它并不想取代已有的框架,而是以高度的开放性与其进行无缝整合。
Spring框架确实给人一种格外清新,爽朗的感觉,仿佛小雨后的绿草丛,既讨人喜欢又蕴藏着勃勃生机。
Spring框架是一个轻量级框架,它大大简化了Java企业级开发,提供了强大,稳定的功能,又没有带来额外的负担,让人们在运用它时有得体和优雅的感觉。
Spring框架有两个主要目标:
(1)让现有技术更易于使用;
(2)促进良好的编码习惯(**实践)
虽然Spring框架是一个全面的解决方案,但它始终坚持一个原则:不重复发明轮子,即在已经有较好解决方案的领域,Spring框架绝不做重复性的实现,如对象持久化和ORM.
Spring只是对现有JDBC,MyBatis,Hibernate等技术提供支持,使之更易用而不是重新做一个实现。
6.1.2 Spring框架的体系结构
Spring框架采用分层架构包括20个模块。这些模块大体分为Core Container,Data Access/Integration.Web,AOP,Aspects,Instrumentation,Messaging和Test,如图6.1所示。
Core是框架最基础的部分,提供了IoC特性。
Context为企业级开发提供了便利和集成的工具。
AOP是基于Spring Core符合规范的面向切面编程的实现。
JDBC提供了JDBC的抽象层,简化了JDBC编码,同时使代码更健壮。
ORM对市面上流行的ORM框架提供了支持。
Web为Spring框架在Web应用程序中断使用提供了支持。
在图6.1包含了Spring框架的所有模块,本书仅涉及其主要模块。
接下来分别对体系结构中的模块作用进行简单介绍。

图6.1 Spring体系结构
1.Core Container(核心容器)
Spring框架的核心容器是其他模块建立的基础,它主要由Beans模块,Core模块,Context模块。Contest-support模块和SpEL(Spring Expression Language)模块组成,具体介绍如下。
(1)Beans模块:提供了BeanFactory,是工厂模式的经典实现。
Spring将管理对象称为Bean.
(2)Core核心模块:提供了Spring框架的基本组成部分,包括IoC和DI功能。
(3)Context模块:建立在Core和Beans的模块基础之上。
它是访问定义和配置任何对象的媒介,其中ApplicationContext接口是上下文模块的焦点。
(4)Context-support模块:提供了对第三方库嵌入Spring应用的集成支持,如缓存(EhCache,Guava,JCache),邮件服务(JavaMail),任务调度(CommonJ,Quartz)和模版引擎(FreeMarker,JasperReports,速率)
(5)SpEL模块:它是Spring3.0版本后新增的模块,提供了Spring Exceressio Language支持,是运行时查询和操作对象图的强大表达式语言
(3)Web
Spring框架的Web层包括WebSocket模块,Servlet模块,Web模块和Portlet模块,具体介绍如下。
(1)WebSocker模块:Spring4.0版本后新增的模块,它提供了WebSocker和SockJS的实现,以及对STOMP的支持。
(2)Servlet模块:也称为Spring-webmvc模块,它包含了Spring的模块-视图-控制器(MVC)和REST Web Service实现的Web应用程序
(3)Web模块:提供了基本的Web开发集成特性,如多文件上传功能,使用Servlet监听器初始化IoC容器,以及Weby应用上下文。
4.其他模块
Spring框架的其他模块还有AOP模块,Aspects模块,Instrumentaion模块,Messageing模块和Test模块,具体介绍如下。
(1)AOP模块:提供了面向切面编程实现。允许定义方法拦截器和切入点,将底阿妈按照功能进行分离,以降低耦合性。
(2)Aspects模块:提供了与AspecyJ的集成功能。
AspectJ是一个功能强大且成熟的面向切面编程(AOP)框架。
(3)Instmmentation模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
(4)Messaging模块:Spring4.0版本后新增的模块。
它提供了对消息传递体系结构和协议的支持。
(5)Test模块:提供了对单元测试和集成测试的支持。
6.1.3 Spring框架的下载及目录结构
Spring1.0版本是在2004年发布的,经过10多年的发展,Spring的版本也在不断地升级优化中。
本书编写是,Spring5.2.3为最新版本,可通过地址“http://repo.spring.io/simple/libs-release-local/org/springframework/spring/”获取。
注意
考虑到该版本对其他开发环境要求太高,本书的项目代码是基于Spring3以上版本编写实现的,对于初学者建议下载Spring3,Spring4的版本,使用方法类似。
这里以Spring3.2.18版本为例,Spring框架开发所需的jar包分为两个部分,具体如下。
1.Spring框架包
Spring 3.2.18版本的框架压缩包,名称为spring-3.2.18.RELEASE-dist.zip,此压缩包可以通过地址"https://repo.spring.io/simple/libs-release-local/org/springframework/spring/3.2.18.RELEASE/"下载。
下载完成后,将压缩包解压到自定义的文件夹中,解压后的文件目录结构如图6.2所示。

图6.2 解压后目录
其中,docs文件夹包含Spring的API文档和开发规范,libs文件夹包含开发需要的jar包和源码;
schema文件夹包含开发所需要schema文件,这些文件中定义了Spring框架相关配置文件的约束。
(1)docs:该文件夹包含Spring框架的相关文档,包括API参考文档,开发手册。
(2)libs:该文件夹存放Spring框架各个模块的jar文件,每个模块均提供3项内容,即开发所需的jar文件,以“-javadoc”后缀表示的API和“-sourcs”后缀表示的源文件。
(3)schema:配置Spring的某些功能时需要用到的schema文件,对于已经集成Spring框架的IDE环境(如MyEclipse),这些文件并不需要专门导入
经验:Spring框架作为开源框架,提供了相关的源文档。
在学习和开发过程中,可以通过阅读源文件,了解Spring框架的底层实现。
这不仅有利于正确理解和运用Spring框架,也有助于开拓思路,提升自身的编程水平。
打开libs目录可以看到57个jar文件,如图6.3所示。

图6.3 libs目录
可以看出,libs目录中的jar包分为3类,其中以RELEASE.jar结尾的是Spring框架class文件的jar包;
以RELEASE-Javadoc.jar结尾的是Spring框架API文档的压缩包;
以RELEASE-sources.jar结尾的是Spring框架源文件的压缩包。
整个Spring框架由19个模块组成,每个模块都提供了这3类压缩包。
在libs目录中,有4个Spring的基础包,它们分别对应Spring核心容器的4个模块,具体介绍如下:
(1)spring-core-3.2.18.RELEASE.jar:包含Spring框架基本的核心工具类。
Spring框架其他组件都要用到这个包里的类,是其他组价的基本核心。
(2)spring-beans-3.2.18.RELEASE.jar:所有应用都要用到的jar包。
它包含访问配置文件,创建和管理Bean,以及进行Inversion of Control(IoC)或者Dependency Injection(DI)操作相关的所有类。
(3)spring-context-3.2.18.RELEASE.jar:Spring提供了在基础IoC功能上的扩展服务,还提供了许多企业级服务的支持,如邮件服务,任务调度,JNDI定位,EJB集成,远程访问,缓存及各种视图层框架的封装等。
(4)spring-expression-3.2.18.RELEASE.jar:定义了Spring框架的表达式语言。
2.第三方依赖包
在使用Spring框架开发时,除了使用自带的jar包,其核心容器还需要依赖commons.logging的jar包。
该jar包可以通过网址“http://commons.apache.org/proper/commons-logging/download_logging.cgi”下载。
下载完成后会得到一个名为commons-logging-1.2-bin.zip的压缩包。
将压缩包解压到自定义目录后,即可找到commons-logging-1.2.jar
初学者学习Spring框架时,只需将其4个基础包,以及commons-logging-1.2.jar复制到项目的lib目录,并发布到类路径中即可。
6.14 Spring框架的优点
Spring框架具有简单,可测试和松耦合等特点,从这个角度出发,它不仅可以用于服务器端开发,也可以应用于任何Java应用的开发中。
关于Spring框架优点的总结,具体如下。
(1)非侵入式设计:Spring框架是一种非侵入式(non-invasive)框架,它可以使用应用程序代码对框架的依赖最小化。
(2)方便解耦且简化开发:Spring框架就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给其容器管理,大大地降低了组件之间的耦合性。
(3)支持:Spring提供了对AOP的支持,它允许将一些通用任务,如安全,事务,日志等进行集中式处理,从而提供了程序的复用性。
(4)支持声明式事务处理:Spring只需要通过配置就可以完成对事务的管理,而无须手动编程。
(5)方便程序的测试:Spring框架提供了对Junit4的支持,可以通过注解方便地测试程序
(6)方便集成各种优秀框架:Spring框架不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts,Hibernate,MyBatis,Quartz等)的直接支持
(7)降低Java EE API的使用难道:Spring框架对Java EE 开发中非常难用的一些API(如JDBC,JavaMail等)都提供了封装,使这些API的应用难度大大降低。
6.2 Spring框架的核心容器
Spring框架的主要功能是通过其核心容器来实现的,因此在正式学习Spring框架的使用之前,有必要先对其核心容器有一定的了解。
Spring框架提供了两种核心容器,分别为BeanFactory和ApplicationContext.
下面将对这两种核心容器进行简单的介绍。
6.2.1 BeanFactory
BeanFactory由org.springframework.beans.facytory.BeanFactory接口定义,是基础类型的IoC容器(关于IoC的具体含义将在6.4节讲解,这里只需要知道其表示控制反转即可),它提供了完整的IoC服务支持。
简单来说,BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用他们的生命周期方法。
BeanFactory接口提供了几个实现类,其中最常用的是org.springframework.beans.factory.xml.XmlBeanFactory,该类可根据XML配置文件中的定义来装配Bean
创建BeanFactory实例时,需要提供Spring框架所管理容器的详细配置信息,这些信息通常采用XML文件形式来管理,其加载配置信息的语法为:

这种加载方式在实际开发中并不常用,了解即可。
6.2.2 ApplicationContext
ApplicationContext是BeanFactory的子接口,也被称为应用上下文,是另一种常用的核心容器。
它由org.springframework.context.ApplicationContext接口定义,不仅包含了BeanFactory的所有功能,好添加了对国际化,资源访问,事件传播等方面的支持。
创建ApplicationContext接口实例,通常采用两种方法,具体如下。
1.通过ClassPathXmlApplicationContext创建
ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作,其使用语法为:

上述代码中,configLocation参数用于指定Spring框架配置文件的名称和位置。
如果其值为applictionContext.xml,则可去类路径中查找名称为applicationContext.xml的配置文件。
2.通过FileSystemXmlApplicationContext创建
FileSystemXmlApplicationContext会从指定的文件系统路径(绝对路径)中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作,其使用语法为:

与ClassPathXmlApplicationContext有所不同的是,在读取Spring框架的配置文件时,FileSystemXmlApplicationContext不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,例如“D:/workspaces/applicationContext.xml”.
如果在参数中写的不是绝对路径,那么方法调用时就会默认使用绝对路径来找。
这种采用决定路径的方式会导致程序灵活性变差,所以并不推荐使用。
在使用Spring框架时,可以通过实例化其中任何一个类来创建ApplicationContext容器。
通常在Java项目中,采用通过ClassPathXmlApplicationContext类来实例化ApplicationContext容器的方式,而在Web项目中,ApplicationContext容器的实例化工作会交由Web服务器来完成。
Web服务器实例化ApplicationContext容器时,通常会使用基于ContextLoaderListener实现的方式,此种方式只需要在web.xml添加代码为:
在后面讲解三大框架整合及项目时,将采用基于ContextLoaderListener的方式由Web服务器实例化ApplicationContext容器
创建Spring框架容器后就可以获取其中的Bean,通常采用以下两种方式
(1)Object getBean(String name):根据容器中Bean的id或name来获取指定的Bean,获取之后需要进行强制类型转换。
(2)<T> T getBean(Class<T> requiredType):根据类的类型来获取Bean的实例。
由于此方法为泛型方法,因此在获取Bean之后并不需要进去强制类型转换。
提升
BeanFactory和ApplicationContext两种容器都是通过XML配置文件加载Bean的。
二者的主要区别在于,如果Bean的某一个属性没有注入,使用BeanFactory加载后,在第一次调用getBean()方法时会抛出异常,而ApplicationContext则在初始化时自检,这样有利于检查所依赖属性是否注入。
因此,在实际开发这,通常都优先选择使用AppHcadonCmKext,而只有在系统资源较少时,才考虑使用BeanFactory.
6.3 Spring框架的入门晨曦
通过前面对Spring框架核心容器的初步了解,下面通过一个简单的入门程序来演示Spring框架的使用,以帮助快速地学习Spring框架。
开发第一个Spring项目,输出“Hello,Spring!”,具体如下。
(1)编写HellSpring类 输出 “Hello,Spring!”
(2)其中字符串内容“Spring”通过Spring框架赋值到HelloSpring类中
1.实现思路及关键代码
(1)下载Spring框架并添加到项目
(2)编写Spring框架配置文件
(3)编写代码通过Spring框架获取HelloSpring实例
2.实现步骤
(1)在MyEclipse中,创建一个名为Cho6_01的Java项目,将Spring框架的4个基础包,以及commons-logging的JAR包复制到lib目录下,需要注意的是,Spring框架的运行依赖于commons-logging组件,需要将相关jar文件一并导入,并发布到类路径下。
为了方便观察Bean实例化过程,可采用log4j作为日志输出,因此也应该将log4j的jar文件添加到项目中,如图6.4所示。

图6.4 导入jar包
(2)在src目录下,创建一个cn.springdemo包,并在包中创建HelloSpring.Java,然后在类中定义一个print()方法,见示例1.
【示例1】 HelloSpring.java
(3)在resources目录下,为该项目添加log4j.properties文件,用来控制日志输出。
log4j.properties文件内容见示例2.
【示例2】 log4j.properties

在resources目录下,编写Spring配置文件.
在项目的classpath根路径下创建application-Context.xml文件(为便于管理框架的配置文件,可在项目中创建专门的Source Folder,如resources目录,并将Spring框架配置文件创建在其根路径下)。
在Spring框架配置文件中创建一个id为helloSpring的,去Bean为Hellospring类的实例,并为who属性注入属性值,见示例3
【示例3】 applicationContext.xml

在上述代码中,第2-5行代码是Spring框架的约束配置。
该配置信息不需要手写,可以在帮助文档中找到。
在Spring框架配置文件中,使用<bean>元素来定义Bean(组件)的实例。
这个元素有两个常用属性,一个是id,表示定义Bean实例的类型。
第8行代码表示在Spring框架的容器中创建一个id为helloSpring的Bean实例,其中class属性用于指定需要实例化Bean的类
经验:(1)使用<bean>元素定义一个组件时,通常需要使用id属性为其指定一个用来访问的唯一名称。
如果想为Bean指定更多的别名,可以通过name属性指定,名称之间使用逗号,分号或空格进行分割。
(2)在本例中,Spring框架为Bean的属性赋值是通过调用属性的setter方法实现的,这种做法称为“设值注入”,而非直接属性赋值。
如属性名为who,但是setter方法名为setSomebody()时,Spring配置文件中应写成name="somebody"而非“ameywho”.
所以在为属性和setter访问其命名时,一定要注意遵循JavaBean的命名规范。
注意
Spring框架配置文件的名称可以自定义,通常在实际开发中都会配置文件名为applicationContext.xml(有时也会命名为beans.xml)。
(5)在cn.test包下创建测试类HelloTest,并在类中编写test1()方法,见示例4
【示例4】 HelloTest.java

在上述代码中没有使用Spring框架,而是直接使用构造方法创建对象helloSpring。
通过helloSpring调用print()方法执行程序后,控制台的输出结果如图6.5所示

图6.5 运行结果(1)
在cn.test包下修改测试类HelloTest。
先在test2()方法中初始化Spring容器,并加载配置文件,然后通过Spring容器获取helloSpring实例(Java对象),最后调用实例中的print()方法,见示例5.
【示例5】 HelloTest.java


执行程序后,控制台的输出结果如图6.6所示

图6.6 运行结果(2)
可以看出,控制台已成功输出了HelloSpring类的输出语句。
比较示例4和示例5的输出结果,在示例5的test2()方法中,并没有通过new关键字创建HelloSpring类的对象,而是通过Spring容器来获取的实现类1对象,这就是Spring IoC容器的工作机制。
在示例5中,ApplicationContext是一个接口,负责读取Spring配置文件,管理对象的加载,生成,以及维护Bean对象与Bean对象之间的依赖关系,负责Bean的生命周期等。
ClassPathXmlApplicationContext是ApplicationContext接口的实现类,用于从classpath路径中读取Spring配置文件。
注意
(1)除了ClassPathXmlApplicationContext,ApplicationContext接口还有其他实现类。
例如FileSystemXmlApplication-Context也可以用于加载Spring配置文件,有兴趣的读者可以查阅相关资料,对其的使用方法做一些了解。
(2)除了ApplicationContext及其实现类,还可以通过BeanFactory接口及其实现类对Bean组件实施管理。
ApplicationContext是BeanFactory的子接口,可以对企业级开发提供更全面的支持。
有兴趣的读者可以自行查阅相关资料,对BeanFactory与ApplicationContext的区别与联系做更多的了解。
通过“Hello,Spring!”的例子,可以发现Spring框架会自动接管配置文件中Bean的创建和为属性赋值的工作。
Spring框架在创建Bean的实例后,会调用相应的setter方法为实例设置属性值。
实例的属性值将不再由程序中的代码主动创建和管理,而改为被动接受Spring框架的注入,使得组件之间可以配置文件而不是用硬编码法方式组织在一起。
提示
快速获取配置文件的约束信息。
在Spring框架的配置文件中,包含了很多约束信息,初学者如果自己动手去编写,不但浪费时间,还容易出错。
spring需要哪些java基础
其实,在Spring框架的帮助文档中,就可以找到这些约束信息,打开Spring框架解压文件夹中的docs目录,在spring-framework-reference文件夹下打开html文件夹,并找到index.html文件,如图6.7所示。

图6.7 Spring的参考文件目录
使用浏览器打开index.html文件后,在页面Overview of Spring Framework的Configuration metadata中,即可找到配置文件的约束信息,如图6.8所示,标记处的配置信息就是Spring框架配置文件的约束信息。
初学者只需将标注处的信息复制到项目的配置文件中使用即可。
此外,由于使用的是Spring3.2版本,所以还需要再复制后的xsd信息中加入版本号信息,其代码为:
![]()
为了更好地学习Spring框架,建议先下载本书中所有配套章节的源代码。
在学习每一章是,如果涉及配置文件的约束信息,就可以将相应章节源代码中的配置文件约束信息复制过来直接使用,在后续的学习中慢慢掌握配置的含义。

图6.8 配置文件的约束信息
6.4依赖注入(DI)与控制反转(IoC)
6.4.1 相关概念
依赖注入(Dependency lnjection,DI)与控制反转(IoC)的含义相同,只不过是从两个角度描述的同一个概念。对于一个Spring初学者来说,这两种称为都很难理解,下面通过简单的语言来描述这两个概率。
当某个Java对象(调用者)需要调用另一个Java对象(被调用者,即被依赖对象)时,在传统模式下,调用者通常会采用“new被调用者”的代码方式来创建对象,如图6.9所示。
这种方式会导致调用者与被调用者之间的耦合性增加,不利于后期项目的升级和维护。

图6.9 调用者创建被调用者对象
在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring框架的容器来创建,它会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。
这样,控制权由应用代码转移到Spring框架容器,控制权发生了反转,这就是Spring框架的控制反转。
从Spring框架容器的角度来看,它负责将被依赖对象赋值给调用者的成员变量,相当与为调用者注入其依赖实例,这就是Spring框架的依赖注入,如图6.10所示

图6.10 将被调用者对象注入调用者对象
提示
相对于“控制反转”,“依赖注入”的说法也许更容易理解一些,即容器(如Spring框架)负责把组价所“依赖”的具体对象“注入”(赋值)给组件,从而避免组件之间以硬编码的方式结合在一起。
6.4.2 依赖注入的实现方式
依赖注入的作用就是在在使用Spring框架创建对象时,动态地将其所依赖的对象注入Bean组件中,其实现方式通常由两种,一种是属性setter方法注入,另一种是构造方法注入,具体介绍如下。
(1)属性setter方法注入:指IoC容器使用setter方法注入被依赖的实例。
通过调用无参构造器或无参静态工厂方法实例化Bean后,再调用Bean的setter方法,即可实现基于setter方法的依赖注入。
(2)构造方法注入:指IoC容器使用构造方法注入被依赖的实例。
基于构造方法的依赖注入通过调用带参数的构造方法来实现,每个参数代表一个依赖。
了解了两个注入方式后,上个示例就是一属性setter方法注入的方式为例,下面修改上述案例,实现使用构造方法的Spring框架的容器在应用中是如何实现依赖注入的。
1.在MyEclipse中,创建一个名为Ch06_02的Java项目,将Spring框架的4个基础包及commons-logging的jar包复制到lib目录中,并发布到类路径下,与上个项目基础配置相同。
2.在src目录下,创建一个cn.springdemo包,并在包中创建HelloSpring.java为其添加无参构造方法和有参构造方法,然后再类中定义一个print()方法,见实例6
【示例6】 HelloSpring.java

(3)在resourecs目录下,编写Spring框架的配置文件,在其中修改id为helloSpring的,以及Bean为HelloSprin类的实例,并通过构造方法为who属性注入属性值。Spring框架配置文件内容见示例7
【示例7】 applicationContext.xml

(4)在cn.test包下,创建测试类HelloTest,并在类中编写test()方法,见实例8
【示例8】 HelloTest.java

执行晨曦后,控制台的输出结果与之前属性setter方法注入结果一致,注意两个HelloSpring.java的差异,使用属性setter方法注入必须要为属性提供getter方法实现属性值的注入,使用构造方法注入必须要为类提供对应参数属性值的构造实现才能注入值。
6.4.3理解 “控制反转”
控制反转(Inversion of Control,IoC),也称为依赖注入,是面向对象编程中的一种设计理念,用来降低程序代码之间的耦合度,在MVC的设计模式中经常使用。
依赖在代码中一般指通过局部变量,方法参数,返回值等建立的对于其他对象的调用关系。
例如,在A类的方法中,实例化了B类的对象并调用其方法以完成特定的功能,即A类依赖于B类。
几乎所有到底应都是由两个或更多的类,通过彼此合作来实现完整功能的。
类与类之间的依赖关系增加了程序开发法复杂程度,在开发一个类的时候,还有考虑对正在使用该类的其他类的影响。
如常见的业务层调用数据访问层实现持久化操作,解决问题的步骤如下.
(1)获取Spring开发包并为工程添加Spring框架支持
(2)为业务层和数据访问层设计接口,申明所需要的方法
(3)编写数据访问层接口UserDao的实现类,完成具体的持久化操作。
(4)在业务实现类中声明UserDai接口类型的属性,并添加适当的构造方法为属性赋值
(5)在Spring的配置文件中,将DAO对象以构造注入的方式赋值给业务实例的UserDao类型属性
(6)在代码这获取Spring配置文件装配好的业务类对象,实现程序功能。
具体实现步骤如下。
(1)在MyEclipse中,创建一个名为Ch06_03的Java项目,在该项目的lib目录中加入Spring支持和依赖的jar包
(2)为业务层调用数据访问层实现持久化操作,见示例9-12
【实例9】UserDao.java

【示例10】UserDaoImpl.java

【示例11】UserService.java
【示例12】UserServiceImpl.java
如以上代码所示,UserServiceImpl对UserDaoImpl存在依赖关系。
这样的代码很常见,但是存在一个严重的问题,即UserServiceImpl和UserDaoImpl高度耦合,如果因为需要变化需要替换UserDao的实现类,将导致UserServiceImpl中的代码也会随之发生修改。
因此,程序将不具备优良的可扩展性和可维护性,甚至在开发中难以测试。
(3)这里将改为使用Spring框架的IoC的方式实现,在配置文件applicationContext.xml中,创建一个id为UserService的Bean,该Bean用于实例化UserServiceImpl类的信息,并将UserDao的实例注入到UserService中,见示例13.
【示例13】 applicationContext.xml

在上述代码中,<property>是<bean>元素的子元素,它用于调用Bean实例中的setUserDao()方法完成属性赋值,从而实现依赖注入。
其中name属性表示Bean实例中的相应属性名,ref属性用于指定器属性值。
(4)在cn.dsscm.test包中,创建测试类IoCTest来对程序进行测试,编辑后其代码见示例14.

执行程序后,控制台的输出结果如图6.11所示。

图6.11运行结果
可以看出,使用Spring容器通过了UserService实现类的addNewUser()方法,调用UserDao实现类的addNewUser()方法,并输出结果。
这就是Spring容器属性setter注入的方式,也是实际开发中最为常用 的一种方式。
分析其使用“控制反转”方式,利用简单工厂和工厂方法模式的思路分析此类问题,其代码见示例15
【示例15】 简单工厂和工厂方法模式
讯享网这里的用户DAO工厂类UserDaoFactory体现了“控制反转”的思想:UserServiceImpl不再依靠自身的代码去获得所依赖的具体Dao对象,而是把这个工作转交给了“第三方”——UserDaoFactory,从而避免和具体UserDao实现类之间的耦合。
由此可见,在如何获取所依赖的对象这件事上,“控制权”发生了“反转”——从 UserServiceImpl转移到UserDaoFactory,这就是所谓的“控制反转”。
问题虽然得到了解决,但是大量的工厂类会被引入开发过程中,明显增加了开发的工作量。
而Spring能够分担这些额外的工作。提供完整的IoC实现,让开发人员得以专注于业务类和DAO类的设计
6.4.4 技能训练1
上机训练 在控制台使用IoC输出
训练要点
使用Spring框架实现依赖注入
需求说明
(1)输出
张三说:“Spring框架的初衷是使Java EE开发应该更加简单”
李四说:“Spring框架的控制反转,也称为依赖注入,是面向对象编程中的一种设计理论,可用来降低程序代码之间的耦合度”
(2)将说话人和说话内容都通过Spring框架注入
实现思路及关键代码
(1)将Spring框架添加到项目
(2)编写程序代码和配置文件(同时配置张三和李子两个Bean)
(3)获取Bean实例,调用功能方法。
6.4.5 深入使用“依赖注入”
通过对示例的学习,我们已经了解了Spring框架的配置及Spring的依赖注入,接下来开发一个网络游戏晨曦,以便更深入地理解Spring框架的“依赖注入”。
问题
如何开发一个网络游戏模拟程序,使其符合以下条件?
(1)可以灵活配置玩家的信息
(2)可以灵活配置装备的信息
分析
程序中包括装备(Equip)和玩家(Player)两类组件。
玩家依赖装备实现速度增项,攻击增效与防御增效。
实现步骤如下。
(1)在MyEclipase中,创建一个名为Ch06_04的Java项目,在该项目的lib目录中加入Spring支持和依赖的JAR包
(2)在cn.games.pojo包中创建装备(Equip)类,其代码见示例16.
【示例】Equip.java

(3)在cn.games.pojo包中创建玩家(Player)类,其代码见示例17
【示例17】Player.java
讯享网
(4)根据以上信息,使用Spring DI配置一个拥有如表6-1所示装备的玩家
表6-1 玩家的装备

【示例18】 applicationContext.xml
(5)在cn.games.test包中,创建测试类GameTest.java来对玩家与装备的信息进行测试,编辑后其代码见示例14
【示例14】GameTest.java
讯享网
执行程序后,控制台的输出结果如图6.12所示。
至此,网络游戏程序的基础模块全部组装完成,并可以正常使用了。
现在总结一下:和Spring有关的只有组装和运行两部分代码,仅这两部分代码就具有Spring依赖注入的魔力。
从配置文件中,可以看到Spring框架管理Bean的灵活性。
Bean与Bean之间的依赖关系放在配置文件里组织,而不是写在代码里。
通过对配置文件的指定,Spring能够精确地为每个Bean注入属性。
每个Bean的id属性是该Bean的唯一标识。
程序通过id属性访问Bean,Bean与Bean的依赖关系也通过id属性完成。
通过Spring的强大组装能力,在开发每个程序组件的时候,只需要明确关联组件的接口定义,并不需要关心具体事现,这就是所谓的“面向接口编程”。
6.4.6技能训练2
上机练习2 练习模拟实现打印机功能
需求说明
开发一个打印机模型程序,使其符合以下条件:
(1)可以灵活配置使用彩色墨盒或灰色墨盒;
(2)可以灵活配置打印页面的大小;
分析
程序中包括打印机(Printer),墨盒(lnk)和纸张(Paper)3类组件,如图6.13所示。
打印机依赖墨盒和纸张

参考步骤
(1)定义lnk接口和Paper接口
(2)使用ink接口和Paper接口开发Printer程序,但在开发Printer程序时并不依赖Ink接口和Paper接口具体的实现类。
(3)开发Ink接口和Paper接口的实现类有ColorInk,GrayInk和TextPaper
(4)组装打印机,并运行调试
本章总结
Spring框架是一个轻量级的企业级框架,提供了IoC容器,AOP实现,DAO/ORM支持,Web集成等功能,其目标是使现有的Java EE技术更易用,并促进养成良好的编程习惯
依赖注入让组件之间以配置文件的形式组织在一起,而不是以硬编码的方式耦合在一起。
Spring框架配置文件是完成组装的主要场所,常用节点包括<bean>元素及其子节点<property>元素。
Spring框架提供了设值注入,构造注入等依赖注入方式。
一,选择题
1.下面关于Spring框架的说法错误的是(B)
A.Spring框架是一个轻量级框架
B.Spring框架颠覆了已经有较好解决方案的领域,如MyBatis框架
C.Spring框架可以实现与多种框架的无缝集成
D.Spring框架的核心机制是“依赖注入”
2.下面关于依赖注入的说法正确的是()
A.依赖注入的目标是在代码之外管理程序组件间的依赖关系。
B依赖注入即“面向接口”编程
C.依赖注入是面向对象技术的替代品
D.依赖注入的使用会增达大程序的规模
3.若Spring配置文件中有如下代码片段,则下面说法正确的是()

A.UserInfo中一定声明了属性:private String userName;
B.UserInfo中一定声明了属性:private Integer userAge;
C.UserInfo中一定有public void setUserName(String username)方法
D.UserInfo中一定有public void setUserAge(Integer userAge)方法
4.以下关于Spring框架核心容器相关说法错误的是(A)
A.Spring框架的所有功能都是通过其核心容器来实现的
B.创建BeanFactory实例时,需要提供Spring框架所管理容器的详细配置信息,这些信息通常采用XML文件形式来管理。
C.ApplicationContext不仅包含BeanFactory的所有功能,还添加了对国际化,资源访问,事件传播等方面的支持
D.通常·在Java项目中,会采用通过ClassPathXmlApplicationContext容器的方式,而在Web项目中,ApplicationContext容器的实例化工作会交由Web服务器来完成
5.以下有关Spring框架的4个基础包说法正确的是()
A.Spring框架的4基础包分别对应Spring Web容器的4个模块
B.Spring框架的4个基础包有spring-core.RELEASE.jar,spring-beans.RELEASE.jar,spring-context.RELEASE.jar和spring-aop.RELEASE.jar
Cspring-context-.RELEASE.Jar是所有应用都要用到的JAR包,它包含访问配置文件及进行IoC或者DI操作相关的所有类
D.spring-core.RELEASE.jar包含Spring框架基本的核心工具类,Spring框架的其他组件都要用到这个包里的类。是其他组件的基本核心。
二、简答题
1.简述Spring框架的优点
2.简述Spring的IoC和DI
三、操作题
在控制台上使用IoC输出,并通过Spring实现·依赖注入,输出内容如下。
张三说:“好好学习,天天向上”
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/4813.html