首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

或许解释清楚Spring技术到底是什么会很困难。通常,Spring是指一个用于构造Java应用程序的轻量级框架,但是这句话包含两个有趣的地方。首先,你可以采用Spring来构造任何程序,这与Apache Struts这样的框架不同,你不限定于只编写web应用。其次,以上解释中的“轻量级”并不意味着类数量很少,或者发行包大小很小,实际上,它指的是Spring哲学原理的总称——那就是最少侵入。Spring是轻量级的,意味着你只需对你的程序代码做很少的改动(假若有的话),而获得Spring核心带来的好处,你也可以在任何时候选择抛弃Spring,你会发现这实在很容易。注意,上面这句话只针对Spring核心本身——很多附加的Spring组件,比如数据访问,需要与Spring框架有相对紧密得多的耦合关系。但是,这些耦合带来的好处显而易见,并且本书从前到后,我们展示的技术都是为了尽量不侵入您的程序代码。

控制反转,还是依赖注入

Spring 框架的核心基于“控制反转(Inversion of Control,IoC)”原理。IoC是一种将组件依赖关系的创建和管理置于程序外部的技术。假设一个例子,类Foo依赖于类Bar的一个实例来进行某些操作。传统的方式,Foo使用new操作符创建一个Bar的实例,或者通过某种工厂类来获得。使用IoC方法,Bar的一个实例(或者其子类的实例)是通过某些外部处理过程在运行时动态传递给Foo的。这种在运行时注入依赖的行为方式,使得IoC后来被改称为另一个含义更明确的名字:“依赖注入(Dependency Injection ,DI)”。通过DI来管理依赖的精确类别,我们在第4章讨论。

注意:你在第4章可以看到,当使用“控制反转”的时候,换用“依赖注入”总是正确的。在Spring的概念范围内,你可以不加区分的使用这两个专用名词,不会带来任何语义变化。

Spring的DI实现是基于两个Java核心概念:JavaBean和Interface。当你使用DI的时候,你可以使得依赖配置与你的代码保持隔离。JavaBeans提供了一种创建Java资源的标准方法,并且这些资源是可以通过标准方式配置的。在第4章,你会看到Spring如何采用JavaBean规范来构成DI配置模型的核心;实际上,任何Spring管理的资源都被应用为bean。如果你不熟悉JavaBean,请参阅我们在第4章开始提供的概述。

接口与DI是相互受益的技术。我们确信,阅读本书的人没有人反对,针对接口设计与编程有助于应用程序的灵活性,但要把采用接口设计的应用程序的各部分连接起来,其复杂度非常高,并且给开发者带来了额外的编码负担。通过采用DI,为基于接口的设计而编写的辅助代码大大减少了,近乎于零。反过来,通过采用接口,你可以获得DI的最大好处,因为你的bean可以采用任何满足其依赖的接口实现。

在DI的语境中,Spring运作得更像一个容器,而非框架——为你应用程序的类提供所有所需依赖的实例,但是它并不像在EJB中创建持久化Entity Bean那样,对你富有侵略性。采用Spring进行DI,你需要做的仅是让你的类遵循JavaBeans的命名规范(在第5章你可以看到,通过Spring的方法注入支持,你甚至这一点都可以不遵循)——不需要从某个特别的超类继承,或者遵循某种私有的命名规范。使用DI时,对你的代码所需要进行的改动至多是让你的JavaBean暴露更多的属性,以便于动态注入更多的依赖关系。

虽然我们把对DI的详细讨论留到第4章,不过现在就可以来看看使用DI而非传统方法的好处。

减少“粘合”代码:DI带来的最大的好处之一就是,它可以奇迹般地消除你为了连接应用程序的各个部件而编写的大量代码。这些代码常常很简单而且琐碎——通过构造一个新的对象来创建依赖。然而,当你需要从JNDI库中查询依赖,或者这些调用不能直接通过调用产生时(比如访问远程资源),这些琐碎的代码可能会变得相当复杂。在这些情形下,DI真的可以简化粘合代码,因为它提供了自动的JNDI查询,以及对远程资源的自动代理。

依赖外置化:你可以将依赖的配置外置,这样你可以无需重新编译代码就重新配置。这给你带来两个有趣的好处。首先,在第4章中可以看到,Spring中的DI是一种理想的配置方式,可以让你在外部自由的配置应用程序的所有选项。其次,依赖外置使得在不同的实现间切换变得非常容易。假设你有一个DAO组件,它针对PostgreSQL数据库进行数据操作,你想把它升级到Oracle。使用DI,你可以简单地重新配置你的业务对象的依赖关系,让它使用Oracle实现而非PostgreSQL实现。

在统一的地方管理依赖:采用传统的方式管理依赖时,你在任何需要的地方创建依赖的对象实例——就在依赖者的内部。在大部分简单的程序中,你会让依赖关系在你的代码中散播,改变它们通常会带来问题。当使用DI的时候,所有关于依赖的信息都通过一个简单的库进行管理,使得管理依赖变得既简单又不容易出错。

提高可测试性:当面向DI设计你的类时,你就可以便捷地替换依赖。当在测试程序的时候,这特别有用。假设一个业务对象进行某些复杂的处理,其中一部分它使用一个DAO对象来访问存储在关系数据库中的对象。在测试的时候,你对测试DAO本身不感兴趣,你只是简单地希望采用不同的数据集来测试你的业务对象。在通常的方式中,你的测试会变得很痛苦,因为你无法简单地把这个DAO实现替换为一个模拟实现,模拟返回你的测试数据。相反,你需要确认你的测试数据库中包含正确的数据,为你的测试使用完整的DAO实现。使用DI的话,你可以为你的DAO对象创建一个模拟实现,然后把它传递给你的业务对象进行测试。这种机制可以扩展到测试你的应用的任何一层,对测试web组件特别有用,你可以创建HttpServletRequest和HttpServeletResponse的模仿实现。

鼓励良好的程序设计:针对DI设计意味着整体上针对接口设计。典型的基于注入的应用程序,其所有的主要组件都是定义为接口的,然后这些接口的具体实现采用DI容器创建并糅合到一起。在DI和基于DI的容器比如Spring出现之前,这种设计在Java中就是可行的,但是通过使用Spring,你免费获得了一个包含完整DI功能的基础,你可以集中精力于建立你的业务逻辑,而非关注支持业务的框架。

在以上列举中可以看到,DI为你的应用程序提供了很多好处,但并不是没有代价的。特别是,对于那些不熟悉代码的人,很难通过DI看到,对于某个特定的依赖,到底是哪个实现被注入到哪个对象中。通常,这是对DI没有经验者的唯一问题;当变得有些经验的时候,开发者会发现由Spring DI给出的应用程序中心视角可以让他们纵览全局。大部分情况下,DI带来的巨大的好处让这一小小的不便显得微不足道,但是在计划你的应用的时候,你应该注意到这一细节。

依赖注入之外

除了先进的DI功能之外,Spring内核本身也是杰出的工具。Spring具有无数的精良的附加功能,而这些都是基于DI的基本原理优雅地设计构建的。Spring提供一个应用所需的所有层面的功能,从用于数据访问的工具API,直到先进的MVC(Model View Controller,模型-视图-控制器)功能。Spring具有的这些功能的重大好处在于,虽然Spring提供它自己的方案,你可以非常容易的把它们和其他工具整合在一起,使得这些工具成为Spring家族中的杰出成员。


 

Spring中的面向方面编程

面向方面编程(AOP)是Java世界中“当红技术”的一种。AOP提供了实现横切逻辑的功能——这一逻辑应用于你应用程序的很多地方,只需要编写一次,就可以把这一逻辑自动在整个应用中实施。AOP当前正在大受瞩目,在大肆宣传的背后,它的确也是一项有用的技术,值得在任何Java开发者的工具箱中占有一席之地。

目前有两种主流的AOP实现。静态AOP,比如AspectJ (www.apsectj.org),提供了编译器的方法来构建基于AOP的逻辑,并把它加入到应用程序中。动态AOP,比如Spring中的这样,允许在运行时把横切逻辑应用到任意一段代码中。两种不同的AOP方法都有其适用面,实际上,AOP提供了与AspectJ整合的功能。这将在第7章中详细介绍。

AOP有很多应用。很多传统的AOP示例都采用的一个典型例子是某种日志机制 , 但是AOP已经找到了远超过这种简易日志应用的用武之地。实际上,在Spring框架自身内部,AOP用于很多方面,特别是事务管理。第7~9章完整地覆盖了Spring AOP的细节,我们展示了在Spring框架内部及你自己的程序中使用AOP的典型例子,还展示了 AOP的性能,以及在哪些领域传统技术比AOP更加适用。

在Spring中访问数据

数据操作与持久化可能是Java世界中被讨论得最多的话题。在访问社群网站,比如www.theserverside.com的时候,你不可能不被关于最新、最伟大的数据访问工具的文章和blog所轰炸。Spring提供了对这些数据访问工具中几个精品的支持。除此之外,Spring对简单直白的JDBC标准API进行了简化封装,使得在很多项目中JDBC成为可行的方案。

到Spring 1.1版本,我们支持JDBC,Hibernate, iBATIS和Java Data Objects (JDO),新近还支持了Apache Jakarta的Object Relational Bridge(OJB)。

Spring中的JDBC支持使得编写基于JDBC的应用变得更加现实了,就算是比较复杂的应用程序也行。对Hibernate、iBATIS 和JDO的支持让本就简单的API更加简化,减轻了开发者的负担。当使用Spring API通过任何工具访问数据时,你可以从Spring优秀的事务支持中获益。对这个问题的详细讨论超过了本章的范围,在第12章中有详细的介绍。

我们发现Spring中最迷人的特性之一,就是易于在同一程序中混合不同的数据访问技术。比如,你可以配合Oracle运行你的程序,使用Hibernate实现大部分的数据访问逻辑。然而,假若你希望使用某些Oracle专有的特性,你可以很容易地用Spring的JDBC API实现那部分的数据访问逻辑。

事务管理

事务管理Spring提供了极好的事务管理抽象层,允许你进行编程式或者声明式事务控制。通过使用Spring的抽象层来进行事务,你可以很容易地抽换底层的数据访问协议和资源管理方式。你可以从一个简单的、本地的、单资源的事务管理起步,转移到全局的、多资源的事务管理环境,而无需更改你的代码。

第12章详细讲述了事务。

简化与整合J2EE

关于一些J2EEAPIs的复杂性,最近有非常多的讨论,特别是关于EJB。从EJB3.0的建议规范可以明显看出,这些争论和建议被专家组所参考,很有希望产生出一个简化得多的EJB API。

然而,现在你就可以使用Spring来为很多J2EE技术提供简化的支持。对EJB来说,有一种选择是创建可以同时构造及访问EJB资源的类。这些类同时减少了这两项任务的很多繁琐工作,也为EJB提供了更加面向DI的API。

对于保存在JNDI中的资源,Spring允许你抛弃那些复杂的查找代码,直接把JNDI管理的资源在运行时作为依赖注入到其他对象中去。为此带来的另一作用就是,你的应用程序与JNDI解耦了,你的代码可以在以后运用于更广的范围中。

到版本1.0.2为止,Spring还没有支持JMS存取。但是,CVS代码库中已经包含很多相关代码,会在1.1版本发布。使用这些代码,简化了对JMS目标的所有交互工作,可以节省为了在你的应用程序中使用JMS而不得不编写的重复代码的数量。

第13章介绍了所有J2EE整合API,包含即将出台的JMS API。

Web层的MVC

虽然Spring可以用于从桌面程序到web程序的几乎所有的地方,但是它还包含了很丰富的类专用于支持编写基于web的应用程序。使用Spring,当你选择如何实现你的web前端时,你拥有了最大的灵活性。

对于任意复杂度的web应用而言,采用一个基于MVC模型的框架被证明是能简化应用维护,以及提高代码重用的。或许最著名的用于web的MVC框架就是Apache Struts(http://struts.apache.org)了。Spring与Struts可以完全整合,允许你在你的Struts类内部使用Spring的DI法则。

除了支持Struts,Spring还提供它自己的优秀的MVC实现,你可以使用很大范围的不同的视图技术,从JSP和Apache Jakarta的Velocity直到Microsoft Excel和Adobe PDF。Spring MVC实现很完善,可以完成你99%的需求任务。对于那剩下的1%,你可以很容易地扩展这一MVC框架,加入你自己的功能。

Spring MVC支持的表现层技术很广泛,还在不断增强。对标准的JSP的支持,Spring提供了很好的tag library支持,除此之外,你还可以从对Jakarta Velocity,FreeMarker, Jakarta Tiles(从Struts中分离出来的)和XSLT的完全整合中获益良多。除此之外,你还可以找到一些基础的视图组件,可以为你的应用程序很容易地增加Excel和PDF输出功能。

我们在第17和18章讲述Spring MVC实现,在第19章讲述Apache Struts。

远程访问(Remoting)支持

在Java中访问或者发布远程组件从未有如此简易过。采用Spring,你可以通过其对远程技术的广泛支持,快速地发布或者访问远程服务。

Spring提供对很多远程存取方法的支持,包括Java RMI, JAXRPC, Caucho Hessia和Caucho Burlap。除了这些远程协议之外,Spring 1.1还有它自己基于HTTP的协议,采用标准的Java序列化。通过Spring的动态代理功能,你的应用可以和特定的远程技术实现解耦,也减少了你需要编写的程序代码。

除了使存取远程组件变得简易之外,Spring也对将被其管理的资源发布为远程服务提供了漂亮的支持。采用这一方法,你可以把你的服务导出为上面提到的任何一种远程存取方法,不需要在你的应用程序中编写任何实现相关的代码。

Mail支持

在很多不同种类的应用程序中,发送Email都是典型需求,因此在Spring框架中得到了高优先级的重视。Spring提供了发送Email的简化API,可以很好地和Spring DI功能结合。Spring支持mail API的插入式实现,并且预先附带了两种实现:一种使用JavaMail,另一种使用Jason Hunter编写的MailMessage类,它可以在http://servlets.com/cos找到,是com.oreilly.servlet的一部分。

Spring提供了在DI容器中创建原型模版的能力,可以用它作为你程序发送所有邮件的基础。这样,定制标题和发送者地址这样的邮件定制化参数就变得简单了。但是,不能在代码以外定制邮件内容。在第15章,我们将详细地讲述邮件支持,以及通过联合Velocity和Spring提供一个解决方案,这一方案可以让你在Java 代码以外定制邮件内容。

计划任务支持

很多有价值的应用都需要某种计划调度能力。不管是为了发送更新消息给用户还是执行一些整理任务,能够安排在某个预先定义好的时间点执行某项任务代码对开发者是非常有价值的。

Spring提供了两种计划调度机制:一种使用Timer类,它是从Java 1.3开始引入的;另一种使用Quartz计划任务引擎。基于Timer类的调度很基础,它只能使用整数毫秒值来进行固定间隔的调度。若使用Quartz,你可以建立复杂的任务计划安排,使用类似于Unix cron格式来定义何时运行某个任务。

第14章将讲述Spring的任务计划支持。

简化的异常处理

在某个领域中,Spring真的能帮助你减少那些重复的无聊的代码,这个领域就是异常处理。Spring哲学的核心之一就是:checked exception在Java中被过度使用了,框架不应该强制你捕获任何你无法恢复的异常——这是作者们一致同意的观点。

在现实生活中,很多框架都设计为减少必须的checked exception的处理代码。但是,其中的很多采用的仍然是checked exception,只是人为地减少了exception类继承树的深度。使用Spring你会发现这一点,因为它采用unchecked exception而为开发者带来了便利,exception继承树明显地变少了。

贯穿本书,你可以看到Spring 异常处理机制是如何减少你必须编写的代码,同时提高你辨别、分类以及诊断错误代码的能力。

源代码级的Metadata(元数据)

源代码级元数据,通常被称作attributes(属性),现在在Java世界中得到了不小的关注,主要是因为关于Attribute的JSR-175标准规范的颁布,它成了Java 5.0的一部分。除了JSR-175,实现Attribute有一大批的开源项目,比如Jakarta Commons Attributes,为当前的虚拟机提供相同的功能。因为很多应用仍然运行于1.3或1.4虚拟机,日后也得持续一段时间,因此存在为这些应用提供attribute支持的期望。

Spring提供了一种可插入的元数据解决方案,你可以在任意点插入任何实现到你的应用中。当前唯一现成的实现是Jakarta Commons Attributes,但是Spring一定会在Java 5.0发布之前提供对JSR-175 Attribute的支持。

Spring对Attribute的支持在全书的多个章节中有涉及,但首先是从第7章对AOP的讨论开始的。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论