1、认识Spring,简介,Spring 的核心是个轻量级(Lightweight)的容器(Container),它是实现IoC(Inversion of Control)容器、非侵入性(No intrusive)的框架,并提供AOP(Aspect-oriented programming)概念的实现方式,提供对持久层(Persistence)、事务(Transaction)的支持,提供MVC Web 框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装,是一个全方位的应用程序框架(Application framework),除此之外,对于现存
2、的各种框架(Struts、JSF、Hibernate 等),Spring 也提供了与它们相整合的方案。,轻量级(Lightweight),轻量级的形容是相对于一些重量级的容器(如EJB 容器)来说的,Spring 的核心包在文件容量上只有不到1MB 的大小,而使用Spring 核心包所需要的资源负担也是很小的,您甚至可以在小型设备中使用Spring 的核心包。,非侵入性(No intrusive),框架原来的用意是提供一个架构的实现,让开发人员可以在基于框架的基础上,快速地开发出遵循架构的所需的应用程序,然而有些框架一旦被使用,应用程序就与框架发生了依赖,例如大量使用了框架的API,或直接继承
3、API 的某些类型等,都会使应用程序组件与框架发生依赖,而无法从框架中独立出来。 Spring 的目标之一是实现一个非侵入性(No intrusive)框架,希望让应用程序几乎感受不到框架的存在,减低应用程序在框架移植时的负担,进一步增加应用程序组件的可重用性(Reusability)。,容器(Container),Spring 提供容器功能,容器可以管理对象的生命周期、对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称、如何产生(Prototype 方式或Singleton 方式)、哪个对象产生之后必须设定成为某个对象的属性等,在启动容器之后,所有的对象
4、都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系。 容器是一个Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在容器都会自动帮您作好。,IoC(Inversion of Control),Spring 最重要的核心概念是Inversion of Control,中文常译为“控制反转”,更具体的另一个名词是Dependency Injection,中文常译为“依赖注入”; 使用Spring,您不必自己在程序代码中维护对象的依赖关系,只需在配置文件中加以设定,Spring 核心容器会自动根据配置将依赖注入指定的对象。,AOP(Aspect-orie
5、nted programming),Spring 最被人重视的另一方面是支持AOP(Aspect-oriented programming)的实现,然而AOP 框架只是Spring 支持的一个子框架。 Spring 的IoC 容器功能与AOP 功能的实现是其重心所在,在Spring 下实现了持久层、MVC Web 框架以及各种企业服务的API 封装,它们的实现有些依重于Spring 的IoC 容器与AOP 功能,Spring 的这些子框架或封装的API 功能彼此可以独立,也可以结合其它的框架方案加以替代,Spring 希望提供one-stop shop 的框架整合方案。,持久层,Spring
6、提供对持久层的整合,如对JDBC 的使用加以封装与简化,提供事务(Transaction)管理功能,对于O/R Mapping 工具(Hibernate、iBATIS)的整合,Spring 也提供了解决的方案。,Web 框架,Spring 也提供MVC Web 框架的解决方案,使用Spring Web 框架的好处是可以善用IoC 与AOP 的功能,您甚至可以轻松地替换使用不同的View 层技术,例如使用JSP、结合Tiles、使用PDF 作为展现给使用者的画面技术。 也可以将自己所熟悉的Web 框架与 Spring 整合,例如Struts、JSF 等,都可以与Spring 整合,而适用于当前所
7、进行的应用程序。,其它企业服务的封装,对于一些服务,例如JNDI、Mail、任务计划(Scheduling)、远程(Remoting)等,Spring 不直接提供实现,而是采取抽象层方式对这些服务进行封装,让这些服务在使用时可以有一致的使用模型,并且在使用上更为简化。,控制反转(Inversion of Control),Spring 的核心概念是IoC,IoC 的抽象概念是“依赖关系的转移”,转移是相对于过去不良的应用程序设计来说的,例如“高层模块不应该依赖低层模块,而是模块都必须依赖于抽象”是IoC 的一种表现,“实现必须依赖抽象,而不是抽象依赖实现”也是IoC的一种表现,“应用程序不应依
8、赖于容器,而是容器服务于应用程序”也是IoC 的一种表现。,控制反转(Inversion of Control),简单地说,在进行模块设计时,高层的抽象模块通常是与业务逻辑(Business logic)相关的模块,它应该具有重用性,而不依赖于低层的实现模块。例如低层模块可能是与硬件相关的软盘存取设计,而高层模块是个存盘备份的程序需求,如果高层模块直接执行低层模块的函数,就对低层模块产生了依赖关系。,控制反转(Inversion of Control),如果以对象导向的方式来设计,依赖反转(Dependency Inversion)的解释为“程序不应依赖实现,而是依赖于抽象接口”。但是您无法直
9、接重复使用Business 类,控制反转(Inversion of Control),可先定义一个IDeviceWriter 接口,控制反转(Inversion of Control),控制反转(Inversion of Control),如果应用程序需要Floppy 存储的话,可以编写一个配置程序如下: Business business = new Business(); business.setDeviceWriter(new FloppyWriter(); business.save(); 同样的,如果应用程序需要USB 磁盘存储的话,可以编写一个配置程序如下: Business bu
10、siness = new Business(); business.setDeviceWriter(new UsbDiskWriter(); business.save();,控制反转(Inversion of Control),IoC 的Control 是控制的意思,其实背后的意义也是一种依赖关系的转移,如果A 依赖于B,其意义即是B 拥有控制权,您想要转移这种关系,所以依赖关系的反转即是控制关系的反转,将控制权由实现的一方转移至抽象的一方,藉由让抽象方拥有控制权,可以获得组件的可重用性,在上面的Java 程序中,整个控制权从实际的loppyWriter 转移至抽象的IDeviceWrite
11、r 接口上,而让Business 依赖于IDeviceWriter 接口,且FloppyWriter、UsbDiskWriter 也依赖于IDeviceWriter 接口。,控制反转(Inversion of Control),程序的业务逻辑部分应该要设计为可以重用的,不应受到所使用框架或容器的影响,这样将来才有可能转移整个应用程序的业务逻辑至其它的框架或容器,如果业务逻辑过于依赖容器,则转移至其它的框架或容器时,就会发生困难。 IoC 在容器的角度,可以用这么一句好莱坞名言来代表:“Dont call me, Ill call you.”以程序的术语来说的话,就是“不要向容器要求所需要的(对
12、象)资源,容器会自动将这些对象给您!”,依赖注入(Dependency Injection),实现IoC 有两种方式:Dependency Injection 与Service Locator,Spring 所采用的是Dependency Injection 来实现IoC,中文翻译为依赖注入。 依赖注入的意义是:“保留抽象接口,让组件(Component)依赖于抽象接口,当组件要与其它实际的对象发生依赖关系时,藉过抽象接口来注入依赖的实际对象。”依赖注入在Martin Fowler 的文章中谈到了三种实现方式:Interface injection、Setter injection 与Cons
13、tructor injection。并分别称其为Type 1 IoC、Type 2 IoC 与Type 3 IoC。,依赖注入(Dependency Injection),在前一个小节中所提到的Business 所实现的是Type 2 IoC,透过Setter(也就是setXXX 方法)注入所依赖的对象,而Type 3 IoC,则是在建构式上注入依赖关系,例如: public class BusinessObject private IDeviceWriter writer;public BusinessObject(IDeviceWriter writer) this.writer = wr
14、iter;public void save() writer.saveToDevice(); ,依赖注入(Dependency Injection),Spring 鼓励使用Setter injection(也就是Type 2 IoC),但也允许您使用Constructor injection,要使用Setter 或是Constructor 来完成依赖关系注入完全视您的需求而定。 使用建构方法注入依赖对象的好处之一是,可以在建构对象的同时,一并完成依赖关系的建立,然而如果要建立的对象关系很多,则必须在建构式上宣告一长串的参数,这时使用Setter 来注入依赖关系会是个不错的选择,因为Setter
15、 有明确的方法名称可用于了解注入对象的作用或类型,使用setXXX() 这样的名称会比必须记忆或查询建构方法上某个参数位置所代表的对象要来得好。,Type 1,Type 1 IoC 是Interface injection,使用Type 1 IoC 时会要求实作接口,对象所在的容器会也会使用这个接口,容器知道接口上所规定的方法,所以可呼叫实作接口的对象来完成依赖关系的注入,例如容器的API 中声明一个IDependency: public interface IDependency public void createDependency(Map dependObjects); ,Type 1
16、,让Business 类实现IDependency 接口: public class Business implement IDependency private Map dependObjects; / 用以记录所依赖的对象 public void createDependency(Map dependObjects) this.dependObject = dependObjects;/ 在这边实现与Business 的依赖关系 public void save() writer.saveToDevice(); 如果要完成依赖关系注入的对象,必须实现IDependency 接口,并将它放置
17、给容器来管理,容器会执行被管理对象的createDependency() 方法来完成依赖关系的建立。,Type 1,由于Type 1 IoC 要求Business 实现容器所规定的接口,这就使得Business 依赖于容器的API,如果日后Business 打算脱离目前这个容器至其它的容器或框架之中,就必须修改程序,想想这样的实作方式,在更复杂的依赖关系中将产生更多复杂的接口,组件与容器(框架)的依赖会更加复杂,最后使得组件无法从容器中脱离。 所以Type 1 IoC 对应用程序或组件来说具有较强的侵入性,使用它来实现依赖注入,会使得应用程序或组件依于容器(框架),因而降低组件的重用性。,依赖注入(Dependency Injection),Spring 的核心是个IoC 容器,可以用Setter 或建构方法的方式来实现您的应用程序对象,至于对象与对象之间的关系建立,则可以透过配置文件设定(一个XML 文件或是一个 .properties 文件),让Spring 在执行时期根据配置文件的设定,为您建立对象之间的依赖关系,您不必特地编写一些程序来自行建立这些对象之间的依赖关系,这不仅减少了大量的程序编写,也降低了对象之间的耦合程度。,