(上一篇文章中我们介绍了《会话EJB系列(二)EJB分类》
,本文的核心为:SessionBean的生命周期)
EJB生命周期:指EJB在运行过程中经历的阶段和状态。
首先强调的是:SessionBean的生命周期是由容器控制的而不是应用程序!对于客户端是完全透明的。但是对于开发者而言,必须了解SessionBean在EJB中的运行规律,才可以更好的管理SessionBean。当然允许被开发者改变。
在前面的文章中我们提到过,可以将EJB容器理解为Spring容器,运行在EJB中的SessionBean就像运行在Spring容器中的POJOBean
一.无状态SessionBean的生命周期
无状态的SessionBean,生命周期比较简单,不需要维护它与客户端之间的会话。
EJB容器通过一个EJB池来维护无状态的SessionBean,该池中有多个无状态SessionBean的实例,切均处于待命状态(准备被客户端调用),当客户端通过JNDI查找实体获取某个无状态的SessionBean时,EJB容器将直接从EJB池中取出一个空闲的EJB供客户端调用,调用完后,将SessionBean再次返回到EJB池中。
一个无状态的SessionBean实例的生命周期,如下:
(1)创建无状态SessionBean实例
(2)EJB容器对EJB实例执行依赖注入(类似Spring的依赖注入)
(3)执行@PostConstruct回调方法
(4)进入待命状态
(5)执行@PreDestory回调方法
(6)垃圾回收
从下图中,可看出无状态的SessionBean的三种状态:不存在状态、待命状态、被销毁状态
二.有状态SessionBean的生命周期
有状态的SessionBean,生命周期稍微复杂,这是因为需要维护客户端的状态。
当它处于待命状态之后,它可以接受一个客户端的调用,一旦有某个客户端调用它之后,那么他就持有该客户端与服务器之间会话状态信息,这些信息导致它只能被该客户端调用,不能被其他客户端调用。如果SessionBean对应的客户端长时间不再调用它,那么EJB容器就不能让它一直处于EJB容器中(占着位置,但又不干活),这对系统资源是一种巨大的浪费,因此EJB容器将会把该SessionBean转入去活状态。
当一个有状态的SessionBean处于去活状态后,如果在有限时间内,该EJB对应的客户端再次调用了该SessionBean,那么EJB容器将会把该SessionBean从去活状态中恢复过来,让它重新转入待命状态,这样他就可以再次向客户端提供服务了。
EJB容器在将一个有状态的SessionBean转入去活状态之前,会先调用该EJB内以@PrePassivate修饰的方法;
EJB容器在将一个处于去活状态的SessionBean恢复到待命状态之前,会先调用该EJB内以@PreDestory修饰的方法
由图可以看出,有状态的SessionBean比无状态的SessionBean多了一个生命周期的状态:去活状态。
因此也就多出来两个Annotation:@PrePassivate,@PreDestory
三.自定义生命周期
掌握了无状态SessionBean和有状态的SessionBean的生命周期后,开发者可以通过EJB定义使用特定Annotation修饰的方法来定制SessionBean的生命周期行为。共5个:@Init、@PostActivate、@PrePassivate、@PostConstruct、@PreDestroy
(此处‘调用’,均指‘被EJB容器调用’)
与无状态SessionBean生命周期行为有关的Annotation有位于javax.annatation包下,2个:
@PostConstruct:在EJB创建之后被调用
@PreDestory:在EJB被销毁之前被调用
与有状态的SessionBean生命周期行为有关的Annotation有位于javax.ejb包下,2个:
@PostActivate:从去活状态中恢复出来后被调用,该方法执行完成后,再次进入待命状态。
@PrePassivate:在去活之前被调用
@Remove :客户端通知服务器删除有状态的SessionBean。
(它修饰的方法与生命周期相关,但并不属于生命周期方法。实际上应该属于一个业务方法,它用于被客户端调用,当客户端调用某个有状态SessionBean的@Remove修饰的方法以后,就相当于客户端通知服务器应该删除该有状态的SessionBean,因此EJB容器将会立即调用该SessionBean中@PreDestory修饰的方法,接下来就销毁该SessionBean。)
总结:
本文主要阐述有状态SessionBean和无状态的SessionBean的在EJB中的运行规律,方便开发者对SessionBean更好的管理,需要强调的是:SessionBean的生命周期是由容器控制的而不是应用程序!