对 Spring 框架还不熟悉的人来说,可能需要先解决一些刚开始接触 Spring 时遇到的问题。实际上,我们编选的这个清单来自于培训 Spring 的新用户时总结的经验和查看 Java 开发社团中的讨论和论坛中内容。我们的目的对这些议题提供一些参考意见,以便在你的下一个项目中决定采用 Spring 时更加胸有成竹。


误解 1 : Spring 不是轻量级的,它打算做所有的事情并且变得越来越庞大和臃肿。


Spring 的主要目标是使基于 POJO 的轻量级开发成为可能。作为开发人员,你应当能够专注于特定领域的业务逻辑而不是基础结构问题和费解的项目合同,应当能够依赖于框架来处理集成方面的事情。然而,当开发企业级应用时,却不可避免地要和很多这类事情打交道。因此,在某种意义上, Spring 确实打算做所有的事情,这些事情正是企业级开发人员期望企业级框架完成的。 Spring 支持如此众多的企业级服务和第三方产品,乍看起来确实有些庞大和臃肿,但是,为了给企业级软件开发提供一个综合的集成平台并同时支持全方位的基于 POJO 的开发, Spring 框架从一开始就设计为非侵入式的和模块化的,你可以并且应该对特定的项目只选择必需的东西,而当需求演变时,你可以不断地增加(或去除)模块, Spring 开发团队强调任何事情应尽可能简单,这不但适用于 Spring 本身,更适用于基于 Spring 构建的应用。


误解 2 : Spring 对简单应用的开发过于强大了(杀鸡用牛刀)。


如上一点所述, Spring 框架可以帮助你保持事情应尽可能简单。你可以在刚开始时仅仅使用需要的部分,当需求更加明晰时再改造和扩展应用,这样一种(开发)环境对促进简单应用的开发是很有意义的,首先,即使是简单应用通常也需要一些企业级服务,如事务性的数据库访问,在这种情况下,最简单的选择也许就是依赖于 Spring 提供的集成式的数据访问和声明式的事务管理;此外,简单的(应用)原型可能以各种方式转变为成品应用,如果由你来负责这样的应用,你会心仪于一个轻量级的然而是可扩展的框架来处理这些需求。


误解 3 : Spring 不能扩展到处理大型的应用。


Spring 已经被全球数百家最大的企业使用在非常大的应用中,在企业级开发环境中很好地使用着 Spring 框架以满足银行、政府部门、航空运输业的应用系统的需求。


Voca 公司就是一个例子,该公司为超过百分之七十的英国人口提供家庭帐单支付服务,并提供英国超过百分之九十的薪水支付服务,依赖于 Spring ,在 2005 年就处理了超过 50 亿个交易,最高日交易量达 7200 万。


其它能证明其对开发效率和性能的提升的大型基于 Spring 的应用还有由 Accenture 完成的法国税务部门的一个在线系统和欧洲专利局的一个企业级应用(据 SpringOne 2006 主题演讲,安特卫普,比利时)。


误解 4 : Spring 强迫你使用还处在实验阶段的面向方面的编程( AOP )。


Spring 的一些强大功能得力于面向方面的编程或 AOP 技术(见第三、四章),但你总是可以选择是否使用这些特殊的特性,此外, Spring 2.0 已经显著地改进了与 AspectJ 的集成,这意味可以有越来越多的选择使用 AOP 的方式。很多用户通过使用 Spring 的基于代理的 AOP 已经对核心概念驾轻就熟,而当需要更为强大的功能时就开始使用 AspectJ 了 。


  在让冗长的说教左右你作出决定之前,有一些事情是必须知道的。首先, Spring 基于代理的 AOP 依赖于对 JDK 的动态代理机制的使用,这意味着这种功能实际上是被 Java 核心语言所支持的;其次, AspectJ 是经过多年研究形成的产品,现在已经成为相当完备的事实上的标准;第三, AOP 特别专注于面向对象编程的一个特定的局限性因而应当被看做一种补充性的而不是革命性的技术。


传统的面向对象编程不能模块化特定的 “ 方面 ” 因而导致代码重复和直交逻辑(如审计、安全性等)的散乱。一旦你越过了最初的学习曲线(其实是非常容易的), AOP 是一个非常自然的解决这些问题的方式。例如,在一个基于 Spring 的应用中,你可以为整个服务层提供事务管理而不需要修改任何代码。这就意味着应用更加灵活并且易于维护,同时保持代码纯粹地专注于业务逻辑。有了这些和其他类似的能力,你就会和越来越多的开发者一样,更加愿意开始 AOP 的实践。


误解 5 : Spring 取代了 Java 企业版 (JEE) 。


这一点是关于 Spring 的最大的误解之一并且是最大的误导之一。实际上, Spring 的主旨在于 JEE 的集成, Spring 相对于传统的、重量级的、基于 EJB 的组件模型提供了一个值得关注的替代物,同时得力于其它 JEE 标准的全部功能。它的一个动机是简化 JEE API 的使用,以使开发者不必被迫重复编写大量的代码;另一个动机是鼓励解除应用程序代码和 JEE 服务之间的耦合。 Spring 提供了一致的方式以提高产能,同时提供了适当的抽象以提高灵活性。


Spring 对 JEE API 的集成支持包括:


l        
 Java Message Service(JMS)
 
l        
 Java Management Extensions(JMS)
 
l        
 Java Transaction API
 
l        
 JEE Connector Architecture(JCA)
 
l        
 Java API fro XML-based Remote Procedure Calls(JAX-RPC)
 
l        
 JavaMail
 
l        
 Java Naming and Directory Interface(JNDI)
 
l        
 和 
 Enterprise JavaBeans(EJB) 
 ,包括版本 
 3 
 。


对一些很重要的 Java 标准版的技术如 JDBC 和 RMI 以及 JEE 版本 5 中的新增的 Java Persistence API(JPA 或称 EJB 版本 3 持久化规范 )Spring 也提供了支持。 Spring 一致性地使用同样的途径来集成较完善的第三方产品,如 Hibernate , iBATIS , Quartz , Hessian 等等。


Spring 的 JEE 集成从未基于“最小公分母”方式,而是尽最大努力保留访问底层技术的最大功能。换句话说,虽然意识到百分之八十的情况下只需使用百分之二十的功能,剩下的百分之八十的功能需要时仍然是可用的。


对这一问题的深入探讨,可参考Rod Johnson 和 Juergen Hoeller所著《Expert One-on-One J2EE Development without EJB》一书。


误解6: Spring 和 EJB 是互斥的技术。


在前一点中,我们把 Spring 描述为 EJB 的“一个值得关注的替代物”,然而, Spring 促进了选择性 - 包括选择使用 EJB 。 Spring 提供了实现 EJB 的支持类并使其可以访问 Spring 容器中的可管理的 Bean 。 Spring 也提供了一个可配置的代理机制,使得 EJB 的客户端代码仅依赖于简单的业务逻辑接口。 EJB 远程访问的细节, JNDI 查找和相关的异常都隐藏于代理之后并由 Spring 进行管理。这种抽象在集成基于 EJB 的遗留代码和新开发的基于 POJO 的代码时是十分有用的,因为客户端不再关心这些细节,这种方式同时提供一条方便的从 EJB 到 POJO 的移植路径。有趣的是,如果你选择使用 EJB3 和与其相关的基于 POJO 的持久化模型 (JPA) ,你会高兴地发现从基于 Spring 的应用进行移植比从基于较早版本的 EJB 应用进行移植要顺畅得多,而且,利用 Spring ,你可以得到 JPA 的所有优点而不必使用 EJB 3 的其它特性。


误解 7 : Spring 不能象 EJB 3 那样利用 Java 5 的标注特性。


Pitchfork 项目,是 Spring 框架的一个补充,支持 JSR-250 和 JSR-220(EJB 3) 标注的一个子集,该项目是 Interface21 和 BEA 公司的一个合作成果,在 Apache 2.0 许可下发布。它不但提供了 WebLogic 的 EJB 3 实现的基础,也使得通过 Spring 框架扩展 EJB 3 的编程模型成为可能。


Spring 2.0 的核心模块提供了对 JPA(EJB 3 的持久化机制 ) 的完整的集成的支持,包括其标注, 还增加了对@AspectJ类型的标注的支持 。其它对比标注的支持包括事务管理、 JMX 配置和依赖校验。


误解 8 :对大型的应用, Spring 的 XML 配置文件会难以维护。


如果不进行适当的管理, Spring 的 XML 文件确实会变得难于编辑和容易出错,对此我们会指出如何利用正确的工具和技巧来解决遇到的一些具体问题:


易于出错:使用合适的工具是必不可少的,一个 XML 文件编辑器可以借助于 DTD 或 XML Schema Definition(XSD) 提供代码填充和校验。 Spring 2.0 主要的特点之一就是使用了基于 XSD 的配置 ( 文件 ) ,从而给( XML )编辑器提供了更多的信息。支持 Spring 的 IDE ,如 InterlliJ 和 Eclipse 的 Spring 插件,提供了更多的功能,如类名的填充和在 bean 定义中获得属性的提示等,如果你可以从一个下拉列表中选择名称,就会节省时间并且不会产生任何输入错误。


难于通查


XML 文件应当拆解开来,以对应于应用系统模块的结构,就像代码一样,合理的做法是把相关的配置信息集中在一起并将不相关的部分清晰地分开。


对简单易变的属性(的维护)过于繁琐


某些键 / 值对应外置于属性文件中,这样就避免了每当这些简单的属性需要修改时都要修改 XML 配置文件。 Spring 提供了配置选项,使得当 bean 的定义中需要这些属性时就能找得到(见第 5 章)。


过多的重复定义


当通用的属性在大量的相关项目中都要进行设置时可以通过 Bean 定义的继承减少重复,例如:单一的“ dataSource ” bean 的定义可以满足很多数据访问 bean 对其的依赖,在此例中,只需一行(配置),一个抽象的父类定义就能提供这种共享属性。


过于宽泛


Spring 2.0 中一个主要的增强就是支持 XSD 和领域特定的名字空间,这就能够为很多常见的配置项目提供更准确的格式,这也为特定领域的 bean 定义提供名字空间或和其它框架的集成提供了方便。


误解 9 : Spring 利用反射完成所有事情,因此会很慢。


Spring 并不是完全通过反射做所有的事,但确实大量使用了反射。因此我们应澄清 Spring 中反射的作用而且应探讨一下通常情况下反射的性能特征。


Spring 利用反射实现其依赖注入,但重要的是要知道这只发生在配置阶段(此时 bean 被关联起来)。从运行时的性能方面看,这与你特意地在 Java 代码中设置这些依赖没有什么区别。


Spring 通过标准的 JDK 动态代理对象在其 AOP 框架中使用反射,这些代理对象是特定地配置在粗粒度的服务层上,提供诸如事务管理、安全以及通过远程访问输出对象,如果对代理对象的方法的调用和执行涉及到网络和 / 或数据库访问,那么由于使用反射代理对性能造成的影响是可以忽略不计的。


在任何情况下,对性能产生影响的论断都应该基于相应的基准而不是主观判断或道听途说,如果你使用的是 Java 1.3 版本,那么有些关于反射的传统说法也许是对的,然而在 Java 1.4 版本中,反射 API 的性能提高了 2,000% 。


误解 10 : Spring 的 MVC 比较复杂,不象 Spring 的其它部分那样简单。


通过基于接口的设计, Spring MVC 的可配置性和可扩展性都十分强大,它利用了成熟的( well-established )设计模式,象策略模式(如 ViewResolver )和模板方法模式(如 SimpleFormController )。不幸的是,很容易将可配置性和可扩展性误认为是复杂性。对 Spring 中的所有东西,你可以并且应该使用需要的部分,但如果花些时间去学习一下还有什么东西可用将会对你大有益处。你将会乐于惊讶地发现每一个 Spring 的 MVC 模块是如此简单和定义完好,每一个相关的单元都着重于实现 HTTP 请求的生命周期和生成页面过程中的一小部分功能,这就促进了业务逻辑和表现逻辑的解耦,进而使应用更加功能强大而灵活。一旦你在一个项目中使用了 Spring MVC 框架,你将会欣赏其强大和易用。用 Spring MVC 实现一个小而简单的项目确实是非常容易的。