通过代码实例跟我学Spring框架从入门到精通Spring框架应用技术.docx
《通过代码实例跟我学Spring框架从入门到精通Spring框架应用技术.docx》由会员分享,可在线阅读,更多相关《通过代码实例跟我学Spring框架从入门到精通Spring框架应用技术.docx(12页珍藏版)》请在冰豆网上搜索。
![通过代码实例跟我学Spring框架从入门到精通Spring框架应用技术.docx](https://file1.bdocx.com/fileroot1/2022-12/11/08c0e223-6c09-4bec-b958-e8328cef027d/08c0e223-6c09-4bec-b958-e8328cef027d1.gif)
通过代码实例跟我学Spring框架从入门到精通Spring框架应用技术
1.1通过代码实例跟我学Spring框架从入门到精通——Spring框架应用技术
1、RodJohnson的《ExpertOne-on-OneJ2EEDesignandDevelopment》
(1)Spring的起源
Spring起源于RodJohnson的《ExpertOne-on-OneJ2EEDesignandDevelopment》,此书已经由电子工业出版社出版,译版名为《J2EE设计开发编程指南》。
同时一个新的JavaFramework发布,同样出自RodJohnson的手笔----这就是SpringFramework。
他在书中大批横批了EJB(2.0版本的)的种种弊端后,忍无可忍的提出了自己的基于实用主义的业务层框架,并把它开源后放到互联网上发表,这就是后来的Spring框架。
(2)Spring框架的产生
SpringFramework实际上是ExpertOne-on-OneJ2EEDesignandDevelopment一书中所阐述的设计思想的具体实现。
在One-on-One一书中,RodJohnson倡导J2EE实用主义的设计思想,并随书提供了一个初步的开发框架实现(interface21开发包)。
而SpringFramework正是这一思想的更全面和具体的体现。
(3)Spring框架的设计者----RodJohnson
RodJohnson在interface21开发包的基础之上,进行了进一步的改造和扩充,使其发展为一个更加开放、清晰、全面、高效的开发框架。
RodJohnson一开始的Spring把自己的核心集中于IOC(控制反转,其实就是用反射的方式调用get和set方法)方面,后来胃口逐渐的膨大,加入了很多新的模块,例如DAO,AOP,ORM,Web等等,把注意力逐渐的转移到整合现有的框架方面,所以有时候它也被称为“万能胶水”,意为没有什么是Spring做不到的。
如今SpringFramework是最流行的轻量级JavaIoC容器。
Rod本人也是Servlet2.4和JDO2.0专家委员会成员,他同时也是一位经验丰富的技术咨询专家。
Rod开了一家咨询公司,提供SpringFramework的技术支持和培训。
(4)Spring框架属于应用层的框架
它提供的是一种“对象管理”的技术(包括生命周期和依赖关系、缓存等)。
2、为什么要提供Spring框架
Spring的目标是实现一个全方位的整合框架,在Spring框架下实现多个子框架的组合,这些子框架之间彼此可以独立,也可以使用其它的框架方案加以替代----Spring框架在设计上可以独立构建应用或者结合已有的框架一起构建应用。
Spring希望提供one-stopshop的框架整合方案。
(1)面向系统设计者:
达到“松藕合”的系统设计目标
由于J2EE平台的复杂性、低性能和可测试性低等等;任何Java系统开发都能从Spring的简单、可测试和松耦合特征中受益。
(2)面向系统实现者:
简化J2EE平台中的应用实现技术
使J2EE简单和易用;促进良好的编程习惯。
3、传统的J2EE系统在应用中所面临的问题
(1)J2EE技术的发展回顾
J2EE技术平台的标准化的特性大大地提升了企业级软件的开放程度,并且得到了整个行业和开发者的广泛认可。
然而,J2EE在一些应用方面开始出现捉襟见肘-----低效、复杂以及依赖容器等导致应用系统的开发的成本比较高。
(2)J2EE技术平台(EJB)的主要问题
1)由于要采用多层结构,因此如果系统设计不良时将导致实现代码复杂,并且无法控制。
2)可选择的技术实现范围太多,而导致开发者在学习方面的成本比较高,无法使初学者快速上手。
3)目前J2EE标准技术只注重中大型系统,小型系统市场被忽视,可伸缩的小中型系统不容易开发。
因此,合理并正确地应用J2EE技术平台来开发并不是件轻松的事情,因为我们在应用某些具体的技术时需要仔细考虑!
1)比如在多层架构的系统中我们需要考虑怎样建立用户界面的接口?
2)在哪里处理业务逻辑?
怎样持久化数据?
3)系统的安全问题如何实现?
4)再比如在各个层中应该使用什么技术?
5)怎样的系统设计既能松散耦合还能灵活改变?
----从而达到如果替换某个层而不影响整体构架?
6)应用系统中如何实现事务处理、并发控制等等。
(3)但拒绝使用EJB并不意味着拒绝J2EE平台中一些良好的思想和解决方案
在J2EE遭遇失败的场景中,EJB通常都扮演着重要的角色。
因此,J2EE社群不断地向着
1)更简单的解决方案
2)更少地使用EJB
3)向轻量级平台等方向发展。
但我们所要明确的是,拒绝使用EJB并不意味着拒绝J2EE平台中一些良好的解决方案------比如,对象的生命周期管理、容器提供基础服务(分离应用组件和基础服务组件的思想)等。
因为,每个企业应用系统都需要这些基础服务。
问题是,我们如何利用现有的框架来提供这些基础服务呢,伴随着这个问题的提出,一个轻量级的J2EE解决方案出现了,这就是Spring框架----能否在轻量级平台中应用EJB中的核心技术?
4、利用SpringIoC和AOP实现J2EE平台中的EJB主要技术
Spring是一个轻量级的控制反转技术(IoC)和面向切面编程(AOP)技术的容器框架。
Spring又是如何实现的呢?
(1)标准J2EE技术平台中的主要的核心思想
1)容器实现对象的生命周期管理
2)分离应用逻辑组件和通用服务组件
3)应用服务器容器可以管理各个组件的事务并可以跨组件的隔离(如EJBCMT特性)
(2)利用SpringIoC实现J2EE平台中所倡导的由容器实现对象的生命周期管理
1)SpringIoC,借助于依赖注入设计模式,使得开发者不再需要自己来管理对象自身的生命周期及其关系,而且能够改善开发者对J2EE和GOF中的各种模式的应用;
2)并且SpringIoC所要求的JavaBean为普通的POJO,而不象EJB那样的必须实现某个接口的要求
从而达到轻量级的实现目标。
(3)利用SpringAOP实现J2EE平台中所倡导的分离应用逻辑组件和通用服务组件
1)SpringAOP,从而达到类似“容器”提供基础功能服务的目标。
2)借助于SpringAOP中所提供的拦截器技术,开发者能够实现以声明的方式使用企业级服务---比如安全性服务、事务服务等。
(4)SpringIoC和SpringAOP组合在一起形成了Spring
1)这样的一个有机整合,使得构建轻量级的J2EE平台的企业级的系统架构成为可能,而且事实证明,非常有效。
2)没有SpringIoC的SpringAOP是不完善的,没有SpringAOP的SpringIoC是不健壮的(Spring=IoC+AOP)。
5、使用Spring的主要的优点----“解耦”和“脱离容器”
(1)Spring框架的核心思想我们可以用两个字来描述,那就是“解耦”。
具体体现如下
应用系统中的各个部分之间(包括应用系统的核心类代码之间和应用系统与所在的框架平台之间)尽量形成一种松耦合的结构,使得应用系统有更多的灵活性;应用系统与其所在的底层应用服务器平台的解耦。
(2)在Spring中是如何实现上面的两种形式的解耦
应用系统内部的类之间的解耦主要通过一种称为控制反转(IOC)的技术来实现;应用系统与底层应用服务器平台的解耦借助AOP技术来实现,Spring内置的AOP支持使得一些本来必须由容器支持的功能,比如事务控制可以脱离开容器运行。
(3)使用Spring后系统主要的优点体现
1)利用其对象“延时依赖注入”思想组装代码,这样一方面减少了在使用这些对象的客户中的大量代码,另一方面也提高系统扩展性,灵活性,实现插件式编程;
2)利用AOP思想达到集中处理业务逻辑并分离附加技术支持代码,从而减少重复代码,构建优雅解决方案;
3)利用其对其它框架的支持比如Hibernate的SessionFactory、事务管理的封装,更简洁地应用和集成Hibernate等O/RMapping框架和其它的框架技术(如Struts等)。
(4)如果我们不用Spring,将额外需要写很多代码!
同时,跟Spring提供的功能相比效果又怎样?
比如事务处理、JDBC数据库访问等实现。
可能会出现“花了精力但又效果不好”局面。
6、Spring中的IoC
(1)IoC=InversionofControl(将原来由程序控制“对象之间的关系”转由容器来实现控制)
IoC:
用白话来讲,就是由容器来控制程序中的各个类之间的关系,而非传统实现中直接在代码中由程序代码直接操控。
这也就是所谓“控制反转”的概念所在:
控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
利用“控制反转”能够减少对象的请求者对服务提供者的特定实现逻辑的依赖,因为我们的组件类不需要去查找或是实例化它们所依赖的其它的组件类。
(2)IOC是一种使应用程序逻辑外在化的设计模式
因为提供服务的组件是被“注入”的而不是被“直接写入”到请求者(客户端)的代码中;这样将能够大大地减少对象的请求者对服务提供者的特定实现逻辑的依赖----因为我们已经将依赖的具体“定位信息”从请求者中分离出来。
(3)我们在应用IoC进行系统开发的基本要求
在代码中不直接创建目标对象,但是描述创建它们的方式。
在代码中不直接与服务对象连接,但在配置文件中描述哪一个组件需要哪一项服务。
程序在运行时,由容器(在Spring框架中是IOC容器)负责将这些对象关联在一起。
(4)代码示例
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http:
//www.springframework.org/dtd/spring-beans-2.0.dtd">
HeLLo,UpperAction
HeLLo,LowerAction
(5)IoC在应用开发中的体现
IoC的抽象概念是“依赖关系的转移”,我们在实际应用中常常提及的下面的各个依赖倒置(DIP)原则其实都是IoC在应用开发中的体现。
1)“高层模块组件不应该依赖低层模块组件,而是模块组件都必须依赖于抽象”是IoC的一种表现
2)“实现必须依赖抽象,而不是抽象依赖实现”也是IoC的一种表现
3)“应用程序不应依赖于容器,而是容器服务于应用程序”也是IoC的一种表现。
7、Spring中的依赖注入
(1)DI=DependencyInjection,对IoC的另一种描述
正在业界为IoC争吵不休时,大师级人物MartinFowler也站出来发话,以一篇经典文章《Inversion
ofControlContainersandtheDependencyInjectionpattern》为IoC正名,至此,IoC又获得了
一个新的名字:
“依赖注入(DependencyInjection)”。
DependencyInjection模式是依赖注射的意思,也就是将依赖关系先剥离(解藕),然后在适当时候再注射到目标系统中。
(2)何谓依赖注入
相对IoC而言,“依赖注入”更加准确地描述了IoC的设计理念。
从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定----也就是由容器动态的将某种依赖关系注入到目标组件之中。
讲的通俗点,就是在运行期,由Spring根据配置文件,将其他对象的引用通过组件的提供的setter方法或者构造方法等进行设定。
(3)IoC和DI的本质:
改变依赖关系
组件和组件的之间的关系的依赖由原来的依赖“目标组件”改变为现在的依赖于“容器”。
为什么要进行改变?
有什么意义?
1)为什么不应该直接依赖“目标组件”
依赖是客观存在的,问题是应该依赖谁?
主要是由于目标组件随着需求的变化而经常改变,我们捕希望在应用系统中由于某个“方面”发生改变而相关联的组件也必须跟着改变---分层的目的也就是能够达到良好的隔离。
2)哪又为什么可以依赖于“容器(Spring框架)”
由于容器相对于应用系统而言应该是相对的稳定的,不会频繁地发生改变----将“可变”和“不变”分离
8、图解“依赖注入”(摘录网上资料)
(1)IT人员的标准“行头”
上面是我们常用的工作装备,笔记本电脑一台、USB硬盘和U盘各一只。
想必大家在日常工作中也有类似的一套行头。
这与依赖注入有什么关系?
(2)图解“依赖注入”---在运行时由容器将依赖关系注入到组件中
图中三个设备都有一个共同点,都支持USB接口。
当我们需要将数据复制到外围存储设备时,可以根据情况,选择是保存在U盘还是USB硬盘,下面的操作大家也都轻车熟路,无非接通USB接口,然后在资源浏览器中将选定的文件拖放到指定的盘符。
这样的操作在过去几年中每天都在我们身边发生,而这也正是所谓依赖注入的一个典型案例,再看上例中,笔记本电脑与外围存储设备通过预先指定的一个接口(USB)相连,对于笔记本而言,只是将用户指定的数据发送到USB接口,而这些数据何去何从,则由当前接入的USB设备决定。
在USB设备加载之前,笔记本不可能预料用户将在USB接口上接入何种设备,只有USB设备接入之后,这种设备之间的依赖关系才开始形成。
对应上面关于依赖注入机制的描述,在运行时(系统开机,USB设备加载)由容器(运行在笔记本中的Windows操作系统)将依赖关系(笔记本依赖USB设备进行数据存取)注入到组件中(Windows文件访问组件)。
这就是依赖注入模式在现实世界中的一个版本。
9、在Spring中为什么要提供“依赖注入”设计理念
(1)应用的目的
我们一直在提倡“组件重用”,但又如何达到以及实现的具体方法?
依赖注入的目标并非为软件系统带来更多的功能,应用它的目的是为了提升“组件重用”的概率,同时也为系统搭建一个灵活、可扩展的平台----安全性、稳定性、可扩展性和可移植性是企业系统的追求目标。
(2)产生的效果---在系统架构方面
提高了组件的可移植性和可重用度,因为依赖注入机制减轻了组件之间的依赖关系—--这也是J2EE平台倡导“松藕合”的系统开发要求。
(3)产生的效果---在系统实现方面
能够更简洁的编程实现,请见文档中的示例说明,可以帮助我们理解其中的含义。
很多初学者常常陷入“依赖注入,何用之有?
”的疑惑。
想来前面和下面的例子可以帮助大家简单的理解其中的含义。
回顾前面“在JBUilder中创建Spring的J2SE的应用”一文中的示例,UpperAction/LowerAction类在运行前,其messageProperty节点为空。
运行后由容器将字符串“HeLLo,LowerAction”注入。
此时UpperAction/LowerAction即与内存中的“HeLLo,LowerAction”字符串对象建立了依赖关系。
也许区区一个字符串我们无法感受出依赖关系的存在。
如果把这里的Message属性换成一个数据源(DataSource),可能更有感觉。
请看下面的示例:
java:
/comp/env/jdbc/testDB
其中DAOBean(假设DAOBean是一个运行在J2EE容器中的组件---如Weblogic或者Tomcat等)中的dataSource将由容器在运行期动态注入,而DataSource的具体配置和初始化工作也将由容器在运行期完成。
对比传统的实现方式(如通过编码初始化DataSource实例),我们可以看到,基于依赖注入的系统实现相当灵活简洁。
(4)上面的示例所反映出的效果
通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定DAOBean中所需的DataSource实例。
DAOBean只需利用容器注入的DataSource实例,完成自身的业务逻辑,而不用关心具体的资源来自何处、由谁实现。
1)提高了组件的可移植性和可重用度
假设我们的部署环境发生了变化,系统需要脱离应用服务器独立运行,这样,由于失去了容器的支持,原本通过JNDI获取DataSource的方式不再有效(因为,现在则需要改变为由某个组件直接提供DataSource)。
我们需要如何修改以适应新的系统环境?
很简单,我们只需要修改dataSource的配置:
com.microsoft.jdbc.sqlserver.SQLServerDriver
jdbc:
microsoft:
sqlserver:
//localhost:
1433;DatabaseName=WebStudyDB
sa
1234
这里我们的DataSource改为由ApacheDBCP组件提供。
没有编写任何代码我们即实现了DataSource的切换。
2)依赖注入机制减轻了组件之间的依赖关系
回想传统编码模式中,如果要进行同样的修改,我们需要付出多大的努力。
因此,依赖注入机制减轻了组件之间的依赖关系,同时也大大提高了组件的可移植性,这意味着,组件得到重用的机会将会更多。
10、对IoC的另一种解释示例---生活中找“对象”(摘录网上资料)
(1)控制倒(反)转
1)常规的方式---自己恋爱
举个简单的例子,我们是如何找女朋友的?
常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。
传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
2)借助于婚介找女朋友
那么IoC是如何做的呢?
有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:
婚姻介绍所。
婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。
简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。
整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。
(2)Spring所倡导的开发方式---由容器帮助我们管理对象的生命周期和关系
1)我们只需要将对象在Spring中进行登记
Spring所倡导的开发方式就是如此,所有的类都会在Spring容器中登记,告诉Spring你是个什么东西,你需要什么东西,然后Spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。
2)所有的类的创建、销毁都由Spring来控制
所有的类的创建、销毁都由Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring。
对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被Spring控制,所以这叫控制反转。
11、如何实现依赖注入----通过reflection来实现DI
(1)Java中提供了对反射(reflection)技术的支持
那么DI是如何实现的呢?
Java1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。
(2)Spring是通过反射技术来实现注入的
(3)示例代码
下面的示例代码可以从配置文件中获得某个组件对象,并且动态地给该组件的message属性赋值。
Propertiespro=newProperties();
pro.load(newFileInputStream("config.properties"));
StringactionImplName=(String)pro.get(actionBeanName);
StringactionMessageProperty=(String)pro.get(actionMessagePropertyName);
Objectobj=Class.forName(actionImplName).newInstance();
//BeanUtils是ApacheCommonsBeanUtils提供的辅助类
BeanUtils.setProperty(obj,"message",acti