清晰的角色划分:控制器,验证器,命令对象,表单对象和模型对象;分发器,处理器映射和视图解析器;等等。
直接将框架类和应用类都作为JavaBean配置,包括通过应用上下文配置中间层引用,例如,从web控制器到业务对象和验证器的引用。
可适应性,但不具有强制性:根据不同的情况,使用任何你需要的控制器子类(普通控制器,命令,表单,向导,多个行为,或者自定义的),而不是要求任何东西都要从Action/ActionForm继承。
可重用的业务代码,而不需要代码重复:你可以使用现有的业务对象作为命令对象或表单对象,而不需要在ActionForm的子类中重复它们的定义。
可定制的绑定和验证:将类型不匹配作为应用级的验证错误,这可以保存错误的值,以及本地化的日期和数字绑定等,而不是只能使用字符串表单对象,手动解析它并转换到业务对象。
可定制的处理器映射,可定制的视图解析:灵活的模型可以根据名字/值映射,处理器映射和视图解析使应用策略从简单过渡到复杂,而不是只有一种单一的方法。
可定制的本地化和主题解析,支持JSP,无论有没有使用Spring标签库,支持JSTL,支持不需要额外过渡的Velocity,等等。
简单而强大的标签库,它尽可能地避免在HTML生成时的开销,提供在标记方面的最大灵活性。
使用ORM工具进行数据访问
Spring在资源管理,DAO实现支持以及实物策略等方面提供了与Hibernate, JDO和iBATIS SQL映射的集成。 对Hibernate,Spring使用了很多IoC的方便的特性提供了一流的支持,帮助你处理很多典型的Hibernate整合的问题。所有的这些都遵守Spring通用的事务和DAO异常体系.。
当您选择使用O/R映射来创建数据访问应用程序的时候,Spring的增加部分就会向您提供重要的支持。首先你应该了解的是,一旦你使用了Spring对O/R映射的支持,你不需要亲自作所有的事情。在决定花费力气,冒着风险建造类似的内部底层结构之前,我们都建议您考虑和利用Spring的解决方案。不管你使用的是何种技术,大部分的O/R映射支持都可以以library样式被使用,因为所有的东西都是被设计成一组可重复利用的JavaBeans。在ApplicationContext和BeanFactory中使用更是提供了配置和部署简单的好处,因此,这一章里的大多数例子都是在ApplicationContext中配置。
使用Spring构建你的ORM应用的好处包括:
测试简单. Spring的IoC使得很容易替换掉不同的实现,Hibernate SessionFacotory的位置,datasource, 事务管理, 映射对象的实现。这样就很容易隔离测试持久化相关代码的各个部分。
异常包装。 Spring能够包装Hibernate异常,把它们从专有的,checked exception变为一组抽象的runtime exception。这样你就可以仅仅在恰当的层处理大部分的不可恢复的异常,使你避免了很多讨厌的catch/throw以及异常声明。你还是可以在你需要的地方捕捉和处理异常。回想一下JDBC异常(包括与DB相关的方言)被转变为同样的异常体系,这就意味着你可以在一致的编程模型中处理JDBC操作。
通用的资源管理。 Spring的application context能够处理诸如Hibernate 的SessionFactory, JDBC的datasource,iBatis的SQLMaps配置对象以及其他相关资源的定位和配置。这使得这些配置的值很容易被管理和修改。Spring提供了有效,简单和安全的Hibernate Session处理。一般的使用Hibernate的代码则需要使用同一个Hibernate Session对象以确保有效和恰当地事务处理。而Spring让我们可以很容易透明地创建和绑定一个session到当前线程;你可以使用以下两种办法之一:声明式的AOP方法拦截器,或通过使用一个外部的template包装类在Java代码层次实现。这样,Spring就解决了在很多Hibernate论坛上出现的使用问题。
综合的事务管理 。 Spring允许你包装你的ORM代码,通过使用声明式的AOP方法拦截器或者在代码级别使用外部的template包装类。不管使用哪一种,事务相关的语义都会为你处理,万一有异常发生也会帮你做适当的事务操作(比如rollback)。就象我们下面要讨论的一样,你能够使用和替换各种transaction managers,却不会使你的Hibernate相关的代码受到影响。更好的是,JDBC相关的代码可以完全和Hibernate代码integrate transactionaly。这对于处理那些没有用Hibernate或iBatis实现的功能非常有用。
避免绑定特殊的技术,允许mix-and-match的实现策略。 虽然Hibernate非常强大,灵活,开源而且免费,但它还是使用了自己的特定的API。此外有人也许会争辩:iBatis更轻便而且在不需要复杂的O/R映射策略的应用中使用也很优秀。能够选择的话,使用标准或抽象的API来实现主要的应用需求,通常是更好的。尤其,当你可能会因为功能,性能或其他方面的原因而需要切换到另一个实现的时候。举例来说,Spring对Hibernate事务和异常的抽象,以及能够让你轻松交换mapper和DAO对象(实现数据访问功能)的IoC机制,这两个特性可以让你在不牺牲Hibernate性能的情况下,在你的应用程序中隔离Hibernate的相关代码。处理DAO的高层次的service代码不需要知道DAO的具体实现。这个方法可以很容易使用mix-and-match方案互不干扰地实现数据访问层(比如在一些地方用Hibernate,一些地方使用JDBC,其他地方使用iBatis),mix-and-match有利于处理遗留下来的代码以及利用各种技术(JDBC,Hibernate,iBatis)的长处.。
Spring提供了一致的事务管理抽象。这个抽象是Spring最重要的抽象之一, 它有如下的优点:
为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、iBATIS数据库层 和JDO
提供比大多数事务API更简单的,易于使用的编程式事务管理API 整合Spring数据访问抽象 支持Spring声明式事务管理
传统上,J2EE开发者有两个事务管理的选择: 全局事务或 局部事务。全局事务由应用服务器管理,使用JTA。局部事务是和资源相关的:例如,一个和JDBC连接关联的事务。这个选择有深刻的含义。 全局事务可以用于多个事务性的资源(需要指出的是多数应用使用单一事务性 的资源)。使用局部事务,应用服务器不需要参与事务管理,并且不能帮助确保 跨越多个资源的事务的正确性。
全局事务有一个显著的不利方面,代码需要使用JTA:一个笨重的API(部分是 因为它的异常模型)。此外,JTA的UserTransaction通常需 要从JNDI获得,这意味着我为了JTA需要同时使用JNDI和JTA。 显然全部使用全局事务限制了应用代码的重用性,因为JTA通常只在应用服务器的环境中才能使用。
使用全局事务的比较好的方法是通过EJB的CMT (容器管理的事务): 声明式事务管理的一种形式(区别于编程式事务管理 )。EJB的CMT不需要任何和事务相关的JNDI查找,虽然使用EJB本身 肯定需要使用JNDI。它消除大多数——不是全部——书写Java代码控制事务的需求。 显著的缺点是CMT绑定在JTA和应用服务器环境上,并且只有我们选择 使用EJB实现业务逻辑,或者至少处于一个事务化EJB的外观(Facade)后 才能使用它。EJB有如此多的诟病,当存在其它声明式事务管理时,EJB不是一个吸引人的建议。
局部事务容易使用,但也有明显的缺点:它们不能用于多个事务性资 源,并且趋向侵入的编程模型。例如,使用JDBC连接事务管理的代码不能用于 全局的JTA事务中。
Spring解决了这些问题。它使应用开发者能够使用在任何环境 下使用一致的编程模型。你可以只写一次你的代码,这在不同环境 下的不同事务管理策略中很有益处。Spring同时提供声明式和编程式事务管理。
使用编程式事务管理,开发者直接使用Spring事务抽象,这个抽象可以使用在任何 底层事务基础之上。使用首选的声明式模型,开发者通常书写很少的事务相关代 码,因此不依赖Spring或任何其他事务API。