EJB和HIBERNATE(转)
void ejbPassivate()
The passivate method is called before the instance enters the
"passive" state.
void ejbRemove()
A container invokes this method before it ends the life of the
session object.
void setSessionContext(SessionContext ctx)
Set the associated session context.
其中的setSessionContext我上面说过。看ejbActivate()、ejbPassive(),为什么会有这两个函数?而Spring不需要实现有同样函数的接口?这是EJB和Spring的对象管理机制的不同造成。EJB implements一般来说,为了复用Bean,会采用一级Cache加上一级InstancePool(StatelessSessionBean是不需要Cache的),从而支持将StatefulSessionBean持久化到磁盘,支持EntityBean的Bean Instance(注意这个Bean Instance和client得到的EntityBean是不同的,它没有和任何的DB Record关联)的复用,这就导致了ejbAcrivate、ejbPassivate等的引入。但是,Spring没有采用这样管理机制,它只有Singleton/Prototype。而Prototype虽然也可以说成是Statefule的,但是它不会在不同的client中复用Object Instance,而是每一个client一个对象,哪怕一万个client,那么就产生一万个Instance,而在EJB中,可能使用100 Instance来服务,将not active的Bean持久化到磁盘,复用Bean Instance。还请注意,这里我不是说EJB中的StatefuleSessionBean好,事实上我发现,一般来说,当并发量很大时,采用节约内存而持久化Bean到磁盘这种策略,I/O瓶颈引起的问题更为严重。
再看,ejbRemove,这个没什么多说的,Spring中你可以选择实现InitializingBean、DisposableBean接口,但是Spring推荐不要这样做,可以写普通的init成员函数,然后在配置文件中指明init-method、destroy-method属性,这样避免和Spring框架的绑定。
总的来说,Spring从对象最基本的引用场景出发,当需要复杂特性的时候,才会采用特殊机制来解决问题,也就是在这时,才会使应用绑定到Spring中。所以,它的侵入性比较低,但是不是“无侵入性”,不是你想的那么美好,当然,也没有“绝对无侵入“的framework。
??????4.2 我觉的Spring IOC的设计思路不够完美
Spring的IOC被一些人当作多么神奇的东西。
EJB具有Spring中所说的那种IOC的能力吗?答案是肯定的。EJB中的EJB引用、资源引用、环境属性都可以说是IOC,不是吗?然而,Spring和EJB的IOC不同在哪里?
Spring注入的特色:主要考虑Local Object的查找,这个时候不需要任何的协议(譬如JNDI),当你需要注入Remote Object的时候,采用RMI协议或者使用第三方Tool(譬如Hessian)。
EJB的特色:无论你的Bean-Bean是否部署在同一台机器上、Client->Bean是否在同一台机器上,肯定需要通过JNDI来查询Bean,只是,如果是它们在同一台机器上的时候,你使用Local接口,这样使得调用变为Local调用,从而提升性能。EJB它从出生时起,就定位为分布式组件架构,一头栽进“distributed”不容易出来了。这个可能就叫“尾大不掉”吧。
这一切的不同,只能说,它们的定位不同。一个更关注Local、一个更关注Remote。Spring仍然坚持它的哲学,从最基本的、大多数的场景考虑起,到特殊需要的时候,再想办法来解决问题。它试图找到J2EE开发和系统能力的均衡点。
可以说,Spring的做法,更加合情合理。但是,我也相信,Spring在”只是为Remote注入提供简单的支持“这一点上有点矫枉过正。我觉的,它可以做的更好,譬如通过作为J2EE标准的JNDI来封装Local、Remote查找。
目前,Spring不怎么关心Remote Object注入,对于需要Remote注入的情况,只提供简单的支持,而且还需要针对expert单独写配置信息。在这里,EJB3.0的做法,我觉的,是目前,最方便、最理智、也是最有前途的。EJB3.0通过@remote、@local就可以让EJB Server做不同的部署。
Spring导出远程对象。
AccountService
Example.AccountService
1199
Spring中注入Remote是怎样做的?
rmi://HOST:1199/AccountService
example.AccountService
看了,这段代码,你就知道了。
这种方法非常的轻量级,从本质上来说,这种方法和JNDI没有任何的不同,这种方法,也需要一个NamingService,还记得RMI编程中,运行服务端的时候,首先运行rmiregistry,这个实际上就是非常简单的NamingService。看来,Rd Johnson对JNDI真是深恶痛绝啊。怎么也不愿意用JNDI。Spring这种方法,也许没有JNDI那样重量级,但是很显然它不能支持工业级分布系统,J2EE发展到今天,JNDI已经成为最核心的技术,它不是简单的Object Naming Service,它提供标准接口来定位用户、微机、网络、对象、服务器等等。它已经广泛而深入的进入J2EE技术的各个领域、成为J2EE系统的纽带。
举个很简单的例子:我需要在Spring应用中动态获取Remote Object,我该怎么做?我需要无缝使用LDAP,我该怎么做?答案是,Spring不能帮到你什么。
那么我就想,Spring为什么不使用JNDI来封装Local、Remote查找两种协议?从而,使用J2EE标准来实现无缝