Session Bean的生命周期事件 Session bean的生命周期里,状态变化会触发生命周期时间的发生。如从 does not exist 状态进入methods – ready pool状态会触发@Postconstruct事件。同样从methods-ready pool状态进入does not exist 状态也会触发@PreDestroy事件。 有些时候,你需要定制sessin bean 的管理过程。例如:你可能想在创建session bean实例的时候初始化字段变量,或在bean实例被销毁的时候关掉外部资源。上述这些,你都可能通过在bean类定义生命周期的回调方法来实现。这些方法指定为回调方法,这不同与EJB2.1,所有的回调方法必须实现,即使是空的。在EJB3.0,bean可以有任意数量,任意名字的回调方法。 •@PostConstruct: 当bean对象完成实例化后,标注了这个注释的方法会被立即调用,每个bean class只能定义一个@PostConstruct方法。这个注释同时适用于有状态和无状态会话bean。 •@PreDestroy:标注了这个注释的方法会在容器销毁一个无用的或者过期的bean实例之前调用。这个注释同时适用于有状态和无状态会话bean。 •@PrePassivate: 当一个有状态的bean实例空闲时间过长,就会发生钝化(passivate)。标注了这个注释的方法会在钝化之前被调用。Bean实例被钝化后,在一段事件内,如果仍然没有用户对bean实例进行操作,容器将会从硬盘中删除它。以后,任何针对该ben方法的调用,容器都会抛出例外。这个注释适用于有状态会话bean。 •@PostActivate:当客户端再次使用已经被钝化的有状态bean时,EJB容器会重新实例化一个Bean实例,并从硬盘中将之前的状态恢复。标注了这个注释的方法会在激活完成时被调用。这个注释只使用于有状态会话bean。 •@Init:这个注释指定了有状态bena初始化的方法,它区别于@PostConstruct注释在于:多个@Init注释方法可以同时存在于有状态session bean 中,但每个bean实例只会有一个@Init注释的方法会被调用。@PostConstruct在@Init之后调用。 •Remove:当客户端调用标注了@Remove注释的方法时,容器将会在方法执行结束后把Bean实例删除。 要处理这些生命周期事件,我们可以为这些事件注册一个回调方法,回调方法可以使用任何名称。但是它必须返回void,不带参数,且不能抛出任何checked exception 。事件注册的过程很简单,只需在回调方法上面加上事件的注释就可以了。 测试一下例子: Lifecycle.java package com.foshanshop.ejb3; /** * 业务接口 * * @author Administrator * */ public interface Lifecycle { public String say(); public void stopSession(); } LifecycleBean.java package com.foshanshop.ejb3Impl; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.Init; import javax.ejb.PostActivate; import javax.ejb.PrePassivate; import javax.ejb.Remote; import javax.ejb.Remove; import javax.ejb.Stateful; import org.hibernate.validator.Range; import com.foshanshop.ejb3.Lifecycle; @Stateful @Remote(Lifecycle.class) public class LifecycleBean implements Lifecycle { @Override public String say() { try{ Thread.sleep(1000*10); } catch(InterruptedException e){ e.printStackTrace(); } return "这是会话Bean生命周期应用例子"; } @Init public void initialize(){ System.out.println("@Init事件触发"); } @PostConstruct public void Construce(){ System.out.println("@PostConstruce事件触发"); } @PreDestroy public void exit(){ System.out.println("@PreDestroy事件触发"); //调用该方法以通知容器,移除该bean实例,终止会话。方法体可以是空的 } @PrePassivate public void serialize(){ System.out.println("@PrePassivate事件触发"); //钝化 } @PostActivate public void activate(){ System.out.println("@PostActivate事件触发"); } @Remove public void stopSession(){ System.out.println("@Remove事件触发"); } } 业务实现后将进行打包,之后创建LifecycleTest.jsp。如下: <%@ page language="java" pageEncoding="UTF-8"import="java.util.*,javax.naming.*,com.foshanshop.ejb3.*"%> <% try{ Lifecycle lifecycle = (Lifecycle) session.getAttribute("lifecycle"); if(lifecycle == null){ InitialContext ctx = new InitialContext(); lifecycle = (Lifecycle) ctx.lookup("LifecycleBean/remote"); session.setAttribute("lifecycle",lifecycle); } out.println(lifecycle.say()); out.println("<br>请注意观察Jboss控制台输出,等待10分钟,"+ "容器将会钝化此会话Bean,@Passivate注释的方法将会执行<br>"); out.println("<font color=red>你可以调用stopSession方法把会话Bean实例删除。"+ "在删除会话Bean时,将触发@PreDestroy事件</font>"); } catch(Exception e) { out.println(e.getMessage()); } %> 使用build.xml文件对web目录下的文件进行打包。(build.xml要放到WebRoot目录下), 如下面的目录结构。 Build.xml: <?xml version="1.0"?> <project name="war" default="war" basedir="."> <target name="war" description="创建WEB发布包"> <war warfile="${basedir}/my.war" webxml="${basedir}/WEB-INF/web.xml"> <fileset dir="${basedir}"> <include name="**"/> <exclude name="build.xml" /> <exclude name="/WEB-INF/web.xml" /> </fileset> </war> </target> </project> 打包OK后,扔到jboss服务run.bat。观看输出结果。