1. Spring工做机制
(1) Spring mvc将全部的请求都提交给DispatcherServlet,它会委托应用系统的其余模块负责负责对请求进行真正的处理工做。
(2) DispatcherServlet查询一个或多个HandlerMapping,找处处理请求的Controller.
(3) DispatcherServlet将请求提交到目标Controller
(4) Controller进行业务逻辑处理后,会返回一个ModelAndView
(5) DispathcherServlet查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
(6) 结果视图对象负责渲染返回给客户端。
2. Spring为何要用
Spring既是一个AOP框架,也是一个IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协做对象)。而后能够很容易地在须要时替换具备相似接口的协做对象。java
AOP 让开发人员能够建立非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务 (好比日志、持久性、事务等)就能够分解成方面并应用到域对象上,同时不会增长域对象的对象模型的复杂性。
IOC 容许建立一个能够构造对象的应用环境,而后向这些对象传递它们的协做对象。正如单词倒置所代表的,IOC就像反过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每个对象都是用其协做对象构造的。所以是由容器管理协做对象(collaborator)。
Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了建立、配置和管理 bean 的方式,组成 Spring框架的每一个模块(或组件)均可以单独存在,或者与其余一个或多个模块联合实现。每一个模块的功能以下:
☆ 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
☆ Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
☆ Spring AOP:经过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。因此,能够很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。经过使用 Spring AOP,不用依赖 EJB 组件,就能够将声明性事务管理集成到应用程序中。
☆ Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不一样数据库供应商抛出的错误消息。异常层次结构简化了错误处理,而且极大地下降了须要编写的异常代码数量(例如打开和关闭链接)。Spring DAO 的面向 JDBC 的异常听从通用的 DAO 异常层次结构。
☆ Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。全部这些都听从 Spring 的通用事务和 DAO 异常层次结构。
☆ Spring Web 模块:Web 上下文模块创建在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。因此,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工做。
☆ Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。经过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
Spring 框架的功能能够用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象能够在不一样 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。
3. IOC 和 AOP
控制反转模式(也称做依赖性介入)的基本概念是:不建立对象,可是描述建立它们的方式。在代码中不直接与对象和服务链接,但在配置文件中描述哪个组件须要哪一项服务。容器 (在 Spring 框架中是 IOC 容器) 负责将这些联系在一块儿。 在典型的 IOC 场景中,容器建立了全部对象,并设置必要的属性将它们链接在一块儿,决定什么时间调用方法。
面向方面的编程,即 AOP,是一种编程技术,它容许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在全部方法和 Java 类中才能实现日志功能。在 AOP 方式中,能够反过来将日志服务模块化,并以声明的方式将它们应用到须要日志的组件上。固然,优点就是 Java 类不须要知道日志服务的存在,也不须要考虑相关的代码。因此,用 Spring AOP 编写的应用程序代码是松散耦合的。 AOP 的功能彻底集成到了 Spring 事务管理、日志和其余各类特性的上下文中。
IOC 容器
Spring 设计的核心是 org.springframework.beans 包,它的设计目标是与 JavaBean 组件一块儿使用。这个包一般不是由用户直接使用,而是由服务器将其用做其余多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,容许经过名称建立和检索对象。BeanFactory 也能够管理对象之间的关系。
BeanFactory 支持两个对象模型。
□ 单态 模型提供了具备特定名称的对象的共享实例,能够在查询时对其进行检索。Singleton 是默认的也是最经常使用的对象模型。对于无状态服务对象很理想。
□ 原型 模型确保每次检索都会建立单独的对象。在每一个用户都须要本身的对象时,原型模型最适合。
bean 工厂的概念是 Spring 做为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。正如Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。
BeanFactory 接口
由于 org.springframework.beans.factory.BeanFactory 是一个简单接口,因此能够针对各类底层存储方法实现。最经常使用的 BeanFactory 定义是 XmlBeanFactory,它根据 XML 文件中的定义装入 bean,如清单 1 所示。
清单 1. XmlBeanFactory
BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));
在 XML 文件中定义的 Bean 是被消极加载的,这意味在须要 bean 以前,bean 自己不会被初始化。要从 BeanFactory 检索 bean,只需调用 getBean() 方法,传入将要检索的 bean 的名称便可,如清单 2 所示。
清单 2. getBean()
MyBean mybean = (MyBean) factory.getBean("mybean");
每一个 bean 的定义均可以是 POJO (用类名和 JavaBean 初始化属性定义) 或 FactoryBean。FactoryBean 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。
IOC 示例
理解控制反转最简单的方式就是看它的实际应用。在对由三部分组成的 Spring 系列 的第 1 部分进行总结时,我使用了一个示例,演示了如何经过 Spring IOC 容器注入应用程序的依赖关系(而不是将它们构建进来)。
我用开启在线信用账户的用例做为起点。对于该实现,开启信用账户要求用户与如下服务进行交互:
☆ 信用级别评定服务,查询用户的信用历史信息。
☆ 远程信息连接服务,插入客户信息,将客户信息与信用卡和银行信息链接起来,以进行自动借记(若是须要的话)。
☆ 电子邮件服务,向用户发送有关信用卡状态的电子邮件。
三个接口
对于这个示例,我假设服务已经存在,理想的状况是用松散耦合的方式把它们集成在一块儿。如下清单显示了三个服务的应用程序接口。
清单 3. CreditRatingInterface
程序员
public interface CreditRatingInterface {
public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}spring
清单 3 所示的信用级别评定接口提供了信用历史信息。它须要一个包含客户信息的 Customer 对象。该接口的实现是由 CreditRating 类提供的。
清单 4. CreditLinkingInterface数据库
public interface CreditLinkingInterface {
public String getUrl();
public void setUrl(String url);
public void linkCreditBankAccount() throws Exception ;
}apache
信用连接接口将信用历史信息与银行信息(若是须要的话)链接在一块儿,并插入用户的信用卡信息。信用连接接口是一个远程服务,它的查询是经过 getUrl() 方法进行的。URL 由 Spring 框架的 bean 配置机制设置,我稍后会讨论它。该接口的实现是由 CreditLinking 类提供的。
清单 5. EmailInterface编程
public interface EmailInterface {
public void sendEmail(ICustomer iCustomer);
public String getFromEmail();
public void setFromEmail(String fromEmail) ;
public String getPassword();
public void setPassword(String password) ;
public String getSmtpHost() ;
public void setSmtpHost(String smtpHost);
public String getUserId() ;
public void setUserId(String userId);设计模式}
服务器
如何创建你的架构,而且怎样让你的各个应用层保持一致?如何整合框架以便让每一个层在以一种松散偶合的方式彼此做用而不用管低层的技术细节?这对咱们来讲真是一种挑战。 这里讨论一个整合框架的策略( 使用3 种受欢迎的开源框架) :表示层咱们用Struts; 业务层咱们用Spring;而持久层则用Hibernate。你也能够用其余FrameWork替换只要能获得一样的效果。
应用程序的分层
大部分的Web应用在职责上至少能被分红4层。 这四层是:presentation(描述),persistence(持久),business(业务)和domain model(域模块)。每一个层在处理程序上都应该有一项明确的责任, 而不该该在功能上与其它层混合,而且每一个层要与其它层分开的,但要给他们之间放一个通讯接口。 咱们就从介绍各个层开始,讨论一下这些层应该提供什么,不该该提供什么。
表示层(The Presentation Layer)
通常来说,一个典型的Web应用的的末端应该是表示层。 不少Java发者也理解Struts所提供的。 象业务逻辑之类的被打包org.apache.struts.Action, 所以,咱们很同意使用Struts这样的框架。
下面是Struts所负责的:
* 管理用户的请求,作出相应的响应。
* 提供一个Controller ,委派调用业务逻辑和其它上层处理。
* 处理异常,抛给Struts Action
* 为显示提供一个模型
* UI验证。
如下条款,不应在Struts显示层的编码中常常出现。 它们与显示层无关的。
* 直接的与数据库通讯,例如JDBC调用。
* 与你应用程序相关联的业务逻辑以及校验。
* 事物管理。
在表示层引入这些代码,则会带来高偶合和麻烦的维护。
持久层(The Persistence Layer)
典型的Web应用的另外一个末端是持久层。这里一般是程序最容易失控的地方。开发者老是低估构建他们本身的持久框架的挑战性。系统内部的持续层不但须要大量调 试时间,并且还常常缺乏功能使之变得难以控制,这是持久层的通病。 还好有几个ORM开源框架很好的解决了这类问题。尤为是Hibernate。 Hibernate为java提供了OR持久化机制和查询服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习起来很方便。 Hibernate的持久对象是基于POJO和Java collections。此外,使用Hibernate并不妨碍你正在使用的IDE。
请看下面的条目,你在持久层编码中须要了解的。
* 查询对象的相关信息的语句。 Hibernate经过一个OO查询语言(HQL)或者正则表达的API来完成查询。 HQL很是相似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你须要学习一些新的HQL语言; 无论怎样,他们容易理解而文档也作的很好。 HQL是一种对象查询的天然语言,花很小的代价就能学习它。
* 如何存储,更新,删除数据库记录。
* 象Hibernate这类的高级ORM框架支持大部分主流数据库,而且他们支持 Parent/child关系,事务处理,继承和多态。
业务层(The Business Layer)
一个典型Web应用的中间部分是业务层或者服务层。 从编码的视角来看,这层是最容易被忽视的一层。 而咱们却每每在UI层或持久层周围看到这些业务处理的代码,这实际上是不正确的,由于它致使了程序代码的紧密偶合,这样一来,随着时间推移这些代码很难维护。幸亏,针对这一问题有好几种Frameworks存在。 最受欢迎的两个框架是Spring和PicoContainer。 这些为也被称为microcontainers,他们能让你很好的把对象搭配起来。 这两个框架都着手于‘依赖注射’(dependency injection)(还有咱们知道的‘控制反转’Inversion of Control=IoC)这样的简单概念。 这篇文章将关注于Spring的注射(译注:经过一个给定参数的Setter方法来构造Bean,有所不一样于Factory), Spring还提供了Setter Injection(type2),Constructor Injection(type3)等方式供咱们选择。 Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler(事务管理控制)、Object Factoris(对象工厂)、service objects(服务组件)——都经过XML来配置联系起来。
后面咱们会举个例子来揭示一下Spring 是怎样运用这些概念。
业务层所负责的以下:
* 处理应用程序的 业务逻辑和业务校验
* 管理事物
* 容许与其它层相互做用的接口
* 管理业务层级别的对象的依赖。
* 在显示层和持久层之间增长了一个灵活的机制,使得他们不直接的联系在一块儿。
* 经过揭示 从显示层到业务层之间的Context来获得business services。
* 管理程序的执行(从业务层到持久层)。
域模块层(The Domain Model Layer )
既然咱们致力于的是一个不是很复杂的Web的应用, 咱们须要一个对象集合,让它在不一样层之间移动的。 域模块层由实际需求中的业务对象组成 好比, OrderLineItem , Product等等。 开发者在这层不用管那些DTOs,仅关注domain object便可。 例如,Hibernate容许你将数据库中的信息存放入对象(domain objects),这样你能够在链接断开的状况下把这些数据显示到UI层。 而那些对象也能够返回给持续层,从而在数据库里更新。 并且,你没必要把对象转化成DTOs(这可能似的它在不一样层之间的在传输过程当中丢失),这个模型使得Java开发者能很天然运用OO,而不须要附加的编码。
域对象层(Domain Object Layer)
这层是编码的着手点,咱们的编码就从这层开始。 例子中Order与OrderItem 是一个One—To—Many的关系。下面就是Domain Object Layer的两个对象:
· com.meagle.bo.Order.java: 包含了一个Order的概要信息
· com.meagle.bo.OrderLineItem.java: 包含了Order的详细信息
好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程序中可能打包在com.meagle.bo内。 更详细一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的 持久对象(presentation classes) 应该分别放在 com.meagle.action和com.meagle.forms包。 准确的给包命名使得你的classes很好分割而且易于维护,而且在你添加新的classes时,能使得程序结构上保持上下一致。
持久层的配置(Persistence Layer Configuration)
创建Hibernate的持久层须要好几个步骤。 第一步让咱们把BO持久化。既然Hibernate是经过POJO工做的, 所以Order和 OrderLineItem对象须要给全部的fileds 加上getter,setter方法。 Hibernate经过XML文件来映射(OR)对象,如下两个xml文件分别映射了Order 和OrderItem对象。(这里有个叫XDoclet工具能够自动生成你的XML影射文件)
- Order.hbm.xml
- OrderLineItem.hbm.xml
你能够在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hibernate的SessionFactory是用来告诉程序 应该与哪一个数据库通讯,该使用哪一个链接池或使用了DataSource,应该加载哪些持久对象。而Session接口是用来完成Selecting,Saving,Delete和Updating这些操做。架构
业务层的配置(Business Layer Configuration)
既然咱们已经有了domain objects,接下来咱们就要business service objects了,用他们来执行程序的logic,调用持久层,获得UI层的requests,处理transactions,而且控制 exceptions。为了将这些链接起来而且易于管理,咱们将使用面向方面的SpringFramework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依赖设置(setter dependency injection)这些方式(可供选择),用XML文件将对象链接起来。 IoC是一个简单概念(它容许一个对象在上层接受其余对象的建立),用IoC这种方式让你的对象从建立中释放了出来,下降了偶合度。
创建咱们的业务服务对象(Building Our Business Service Objects)
Business Object中的Setter方法接受的是接口,这样咱们能够很松散的定义对象实现,而后注入。 在咱们的案例中,咱们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。因为在这个例子中使用了Hibernate,咱们能够很方便的用其余持久框架实现同时通知Spring 有新的DAO可使用了。
在面向接口的编程中,你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久机制的:)。
Spring 和Bean 的还有一点要注意的: bean能够以用两种方式创造。 这些都在单例模式(Sington)和原型模式(propotype)中定义了。 默认的方式是singleton,这意味着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候容许新建实例的。当每一个用户须要获得他们本身Bean的Copy时,你应该仅使用prototype模式。 (更多的请参考设计模式中的单例模式和原形模式)
提供一个服务定位器(Providing a Service Locator)
既然咱们已经将咱们的Serices和DAO搭配起来了。咱们须要把咱们的Service显示到其余层。 这个一般是在Struts或者Swing这层里编码。一个简单方法就是用服务定位器返回给Spring context 。固然,能够经过直接调用Spring中的Bean来作。mvc
4. 说说Spring AOP和IOC AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程, AOP很是适合开发J2EE容器服务器. IOC就是Inversion of Control,控制反转。在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。