EJB3.0和Spring比较
(译“POJO Application Frameworks: Spring Vs. EJB 3.0”)
摘要:
阅读“POJO Application Frameworks: Spring Vs. EJB 3.0”一文的读书笔记,翻译其中部分,主要分6点讲述两者的差别。
0.比较目录
1) Vendor
2) Service Integration
3) Flexibility in Service Assembly
4) XML versus Annotation
5) Declarative Services
6) Dependency Injection
1. 厂商无关性(Vendor
Java平台最具竞争力的优势是厂商无关,(不依赖某个特别的厂商)。EJB3.0的标准也是开放的,并且继承了这一优势。EJB3.0的规范是由包括几乎所有Java社区内的开源和商业组织定义并支持的。EJB3.0隔绝了开发者和应用服务的具体实现。比如说:JBoss的EJB3.0是在Hibernate的基础商实现的,而Oracle的EJB3.0是基于TopLink实现的。但开发者在使用EJB3.0开发企业应用时,即不需要学习Hibernate也不需要学习TopLink,EJB3.0依然能够在JBoss或Oracle上面运行得很好。厂商无关性时EJB3.0框架现在区别于任何其他POJO中间件框架的一大特色。
当然,也有一些EJB3.0的批评者立刻指出,EJB3.0的规范还没有最终定稿,EJB3.0得到业界主要J2EE厂商完全接受还有一到两年的路要走。是的,是这样,但是既便现在企业软件采用的应用服务还不支持EJB3.0,但是,(在将来)仍然能够通过下载安装“可嵌入(embeddable)”EJB3.0产品来获得支持。这方面走在前面的JBoss就已经推出的可嵌入EJB3.0产品,开源并且支持所有兼容J2SE-5.0的环境,现在正处于beta测试阶段。其他厂商也正在迅速跟进,很快会推出他们自己的可嵌入的EJB3.0产品,特别是EJB3.0规范中的“数据持久化”部分。
另一方面,Spring是一个非基于标准的技术解决方案,并且在将来很长一段时间也将继续维持这样的状况。你可以在任何应用服务上使用Spring框架,但同时意味着你的应用已经和Spring以及Spring所选用的应用服务套牢了。
- Spring框架是一个开源项目(而不是标准),自己定义了一套XML配置文件大纲以及程序接口。几乎所以的开源项目都是这样。从长远考虑,使用Spring框架的企业应用恐怕得更关注Spring项目的运作情况(以及Interface21 Inc. ――大部分Spring的核心开发人员都来自于Interface21 Inc.)。另外,如果企业应用中采用了Spring专用服务(Spring-specific services),比如Spring事务管理或Spring MVC,事实上这个企业应用已经和Spring牢牢绑死了。
- Spring没有实现和最终服务提供者的隔离。比如,现在在选择数据持久化服务时,Spring框架使用不同的DAO和Helper类以利用JDBC、Hibernate、iBatis或JDO。所以,如果你打算改变数据持久化方式,比如从JDBC改为Hibernate,你就需要重构你的应用代码了,新的Helper类编写也是不可避免的。
2.服务集成 (Service Integration)
Spring框架站在一个高于应用服务和服务相关类库的层次上。服务集成代码(如:数据访问和Helper类等)位于框架中,并直接暴露给应用开发者。EJB3.0则相反,EJB3.0框架牢牢的集成到应用服务中,所有的服务集成代码都被封装到标准接口下面。
这样的设计使得EJB3.0的厂商可以集中优化总体性能,优化开发者体验。例如:在JBoss EJB3.0实现中,当你使用EntityManager持久化一个实体Bean POJO时,底层的Hibernate会话事务被自动的指派调用JTA事务的方法,并在JTA事务提交时被提交。使用一个简单的注释(annotation)@PersistenceContext,就可以将EntityManager和底层的Hibernate事务绑定到一个有状态的会话Bean中应用事务中。应用事务在一个会话中跨越多线程,这在Web应用的事务处理中非常有用,比如一个包含多页面的购物车功能。这样的简单性和接口集成都得益于EJB3.0、Hibernate、JBoss中的Tomcate的紧密集成。在Oracle EJB3.0框架中的情况是一致的,只不过Hibernate换成了TopLink而已。
EJB3.0服务集成的另一个例子是集群支持。如果你将一个EJB3.0应用部署到一个服务集群中,所有的负载均衡、分布缓存、状态复制等全都自动的生效了。底层的集群服务隐藏在EJB3.0编程接口后面,屏蔽了所有的复杂性。
在Spring这边,优化框架和服务之间的交互要困难得多。比如,如果要使用Spring的声明式事务服务来管理Hibernate事务,必须手工显式的在XML配置文件中配置Spring的TransactionManager和Hibernate的SessionFactory对象。Spring应用的开发者必须显式的管理那些跨越多个HTTP请求的事务。另外,Spring没有简单的利用集群的方法。
3. 服务装配灵活性 (Flexibility in Service Assembly)
因为Spring中的服务集成代码是以编程接口的形式发布的,所以应用开发者在装配服务时可以获得极大的灵活性。这使得开发者可以装备自己的轻量级的应用服务。Spring 的一个最普遍的应用就时粘合Tomcat和Hibernate来支撑简单的数据库驱动应用。在这种情况下,Spring提供事务服务,Hibernate提供持久化服务,这样的配置构成了一个迷你型的应用。
EJB3.0应用服务没有给你这类可以选择的灵活性。在大多数情况下,你将得到一套已经打包好得特性,尽管其中有些你根本就用不着。当然,如果应用服务内部是模块化设计,比如JBoss,你可以剥离这些你不用得部分。这样得定制对一个成熟得应用服务是非常有价值的。
当然,如果应用发生伸缩,范围超出了单一服务节点,你就应该在应用服务中加入其他服务,如:资源池、消息队列、集群等。当加入这些后,Spring的解决方案已经和EJB3.0 一样重量级了。
使用Spring,服务装配的灵活性使得利用模拟对象(mock object)非常容易。模拟对象可以在单元测试中代替真实的服务对象,从而使得容器外测试得以成为可能。EJB3.0应用中,大部分组件都是简单的POJO,也很容易在容器外进行测试。但是,那些牵涉到容器对象的测试(如:EntityManager),容器内测试才是最佳选择,比使用模拟对象测试更简单、更健壮、更准确。
4. XML v.s 属性注释(XML Versus Annotation)
再应用开发者看来,Spring的编程接口主要是基于XML配置文件的基础上,而EJB3.0则大量使用Java注释。XML文件可以表达复杂的(从属)关系,但是也非常冗长而且不够健壮。注释则比较简单,但却很难表达复杂关系和子属结构。
Spring和EJB3.0分别对XML配置文件和Java注释的选择是由两种框架背后的构架设计所决定的。因为注释只能容纳非常少量的配置信息,所以只有预集成的框架(大多少工作已经在框架内部完成)可以大量使用注释作为其配置解决方案。正如同我们已经讨论的那样,EJB3.0符合这种要求,而Spring,作为一种DI框架,就不能这么做。
当然,EJB3.0和Spring都在发展中都相互借鉴了对方的长处,都在不同的程度上支持XML配置或Java注释配置。XML配置文件在EJB3.0中也被用来配置注释的缺省行为。而在Spring中,注释也用来配置Spring服务。