以上实例演示了Spring 和 EJB 3.0如何实现有状态的对象。尽管在功能方面相近,处理方式上则有明显的差异。

图4. 客户端的状态管理。Spring将状态组件存储在由web容器管理的HttpSession内。


图5. EJB的状态管理。客户端通过代理对象与EJB组件交互。这样组件的状态可由EJB容器管理。
EJB采用SFSB的方式有几个优点。第一,在设计上允许SFSB在内存和持久性存储之间交换,使应用服务器可以平衡资源分配以改善性能。第二:SFSB运行在单独的进程内,应用系统的各层可以独立地配置和维护。第三,SFSB可以实现SessionSynchronization接口,这样事务回滚事件发生时,可以返回到bean的初始状态。
对于SFSB的批评一般集中在:与无状态的架构相比,性能和伸缩性不够好。针对这一点,Spring框架设计为以无状态为主。对于很多应用来说,状态是个重要指标。通常保存状态的几种方式是:数据库,HTTP Session,或内存。在上例中,基于Spring的购票代理可采用任一种方式管理状态,见表4。
表4. Spring中状态会话 Bean的替代方案
|
SFSB 的替代方案
|
优点
|
缺点
|
|
数据库
|
所有应用服务器共享
|
应用各层中最不灵活的层,如果设置二级缓存,则需复制数据。
|
|
HTTP Session
|
易用
|
必须复制数据,不能感知事务。
|
|
内存
|
所有应用服务器共享,效率高于数据库
|
必须复制数据,不能感知事务。
|
对于SFSB伸缩性问题的指责同样适用于表中的各方案,另外还需要重新开发SFSB已经具备的功能。在确定状态管理模式时,这些因素需要综合加以考虑。
Spring和EJB 3.0均提供了组件扩展点,使开发人员可将组件绑定到托管bean的生命周期。Spring提供了InitializingBean 和 DisposableBean接口,在bean初始化后和销毁前得到通知。EJB组件在创建后、销毁和钝化前、激活后,可通过设置获得通知。
最后,将bean的会话状态和事务同步是另一个要重点解决的问题。默认情况下,在事务回滚时,所有和事务相关的资源也相应回滚(如数据库和消息系统)。如果bean是有状态的,就会产生bean的状态同持久性数据存储不一致的问题。
EJB 3.0中SFSB基于容器管理的事务管理方式可实现SessionSynchronization接口以获取事务通知。基于Spring的方案则需以定制的方式实现相应的功能。
状态管理——小结
Spring 和EJB 3.0 都支持应用的状态管理机制。EJB 3.0采用SFSB实现状态管理,而Spring通过原型bean达到同一目标,这时性能和伸缩性是主要的考虑因素。两者的比较见图5。
图5. Spring 和 EJB 3.0.状态处理的比较
|
特性
|
Spring
|
EJB 3.0
|
|
表示状态的结构
|
原型bean
|
状态会话 Bean
|
|
实例管理
|
单例、原型、请求、会话、全局会话
|
每次生成新实例
|
|
生命周期管理
|
√ (初始化/销毁)
|
√
(创建/销毁、激活、钝化)
|
|
事务感知
|
--
|
√(SessionSynchronization 接口)
|
|
标准化
|
没有
|
√
|
五、结论
本文对于Spring应用框架和EJB 3.0规范在持久化、事务处理、状态管理等方面做了技术上的比较。两者有很多相近之处,其主要的差异体现在:状态管理模式、配置方式、扩展性。如果要开发的应用在状态管理方面需求很高,应优先考虑EJB 3.0 SFSB的方案。如果应用中交互会话强度较高,SEAM(基于SFSBs 和 JSF)是好的选择。
Spring在应用开发的很多方面提供了比EJB更灵活的选择,这一点在持久化和事务管理提供程序方面尤为显著。另一方面,也无疑增加了配置的复杂性。EJB 3.0虽欠灵活,但以其紧凑的技术架构、基于注释的配置方式、异常处理的配置方案等特性简化了应用开发过程。
标准化问题:Spring框架中集成了很多行业标准,比如JTA, JDBC, and JMS等,但Spring还不是一个java标准。
非常幸运的是,Spring和EJB 3.0之间并不是相互排斥的。可以将两种技术结合起来以取长补短。