如何开发会话bean
有状态会话Bean生命周期
有状态会话Bean的生命周期由容器控制,Bean的客户实际上没有Bean的直接引用。当我们部署一个EJB时,容器会将Bean的几个实例分配给组件池。当客户请求一个Bean时,J2EE服务器将分配一个预先实例化的Bean。在客户的一个会话中,Bean只能被引用一次,并且可以执行Bean的多个方法。如果另一个客户请求同一个bean,容器检查池中的空闲Bean(它们不在方法或事务中,如果一个客户长时间引用一个Bean,但执行一个方法后需要等待另一个方法,这个时间也是空闲的)。如果所有实例都用完了,将自动生成一个新的实例,并将其放入池中,分配给请求者。当负载减少时,池将自动管理Bean实例的数量,并从池中释放冗余实例。
有状态会话Bean的初始化状态不存在。当一个Bean被客户引用时,newInstance()、setSessionContext()和ejbCreate()的方法按顺序调用,这与第一节提到的无状态调用顺序相同。当方法处于就绪状态时,如果客户调用remove()方法,将返回到不存在状态,并触发Bean的ejbRemove()方法。如果客户端长时间不调用bean或者服务器准备释放一些内存资源,容器会从组件池中钝化这些Bean,钝化进程容器会调用Bean的EJB passive()方法,让程序员在钝化Bean时有机会释放分配的资源。当客户请求一个钝化的Bean时,容器可以激活Bean,激活流程容器会调用ejbActivate(),给程序员一个机会,在Bean转到方法现成状态时,分配Bean需要的资源。
Bean本身可以管理事务(BMT Bean管理的事务),或者容器可以管理事务(CMT容器管理的事务)。对于CMT,容器在方法开始时打开事务,在方法结束时实现事务。Bean开发人员可以通过afterBegin()、beforeCompletion()和afterCompletion(Boolean)获得事务的各种状态。如果afterCompletion(Boolean)中的布尔变量为真,则事务完成,如果为假,则事务取消。
编写一个有状态会话Bean程序
假设这次我们要为一个资金组织编写一个资金账户的Bean组件,它将为资金管理系统提供一个资金账户的基本功能。为了描述清楚有状态会话Bean的特点,我们将其简化为提供三个业务逻辑接口:addFunds()方法将资金添加到一个资金账户,removeFunds()方法从资金账户中取出资金,getBalance()方法为我们提供了一个资金账户余额查询。我们将这个Bean命名为StatefulAccount。
设计有状态会话Bean至少包括四个步骤:
开发主界面
开发组件接口
开发Bean实现类
编写部署文件
注:本节假设您使用的是Windows操作系统。如果使用其他操作系统,可能会影响存储路径和JDK命令,但与程序代码和部署文件的内容无关。
1.开发主界面(StatefulAccountHome.java):
是Bean开发者编写的Bean的主接口程序,负责控制Bean的生命周期(生成、删除和查找Bean)。只需要开发者给出一个主接口类,类方法的实现由容器完成。
主接口扩展了javax.ejb.EJBHome接口,参考avax.ejb.EJBHome接口定义如下:
包javax.ejb
导入Java . RMI . remote;
导入Java . RMI . remote exception;
公共接口EJBHome扩展远程{
公共抽象EJBMetaData getEJBMetaData()抛出RemoteException
公共抽象HomeHandle getHomeHandle()抛出RemoteException
公共抽象void remove(Object obj)抛出RemoteException,RemoveException
公共抽象void remove(Handle句柄)抛出RemoteException,RemoveException
}
方法getEJBMetaData()返回EJBMetaData接口的引用来获取Bean的信息,EJBMetaData不是远程接口。这个类扩展了java.io.Serializable,所以它是可序列化的,具有序列化的特征。
getHomeHandle()方法返回主对象的句柄,它是主接口StatelessAccountHome的持久引用。这个类扩展了java.io.Serializable,所以可以序列化,HomeHandle对象可以传递给另一个JVM,而不需要传递安全信息,这样新的应用程序就可以获得主接口,创建和获取Bean实例,而不需要使用JNDI。
Remove()方法用于删除Bean的实例。对于会话Bean,删除操作会将被引用的Bean返回到池中,池将管理其生命周期。
一般来说,通常将主接口的命名规则指定为
大多数逻辑方法已经被EJBHome定义了,所以没有必要在我们要设计的远程主机接口中重新定义它们。值得注意的是,我们需要为这个接口定义一个create()方法来获取对实例Bean的引用,返回的对象类型是组件接口类StatefulAccount。它与第二节中StatelessDateHome类的定义基本相同,只是Create()方法需要一个double fund参数。当客户创建Bean引用时,我们将通过该参数初始化资金帐户的余额。基金价值的状态将由容器来维护。
StatefulAccountHome.java电码:
导入Java . RMI . remote exception;
导入javax . EJB . create exception;
导入javax . EJB . EJB home;
公共接口StatefulAccountHome扩展EJBHome{
public stateful account create(double fund)抛出RemoteException,CreateException
}
假设我们把它保存到d:\ EJB \ stateful account \ src \ StatefulAccountHome.java。
2.开发组件接口(StatefulAccount.java):
当远程用户调用主接口类生成方法(create(double))时,客户希望获得一个组件的远程引用,所以EJB容器要求你为这个Bean的所有方法提供一个接口类,类的实现在部署时由容器自动生成,就像远程主接口StatefulAccountHome一样。
组件接口扩展了avax . EJB . EJB object接口,参考avax . EJB . EJB object接口定义如下:
包javax.ejb
导入Java . RMI . remote;
导入Java . RMI . remote exception;
公共接口EJBObject扩展远程{
公共抽象EJBHome getEJBHome()抛出RemoteException
公共抽象句柄getHandle()引发RemoteException
公共抽象对象getPrimaryKey()引发RemoteException
公共抽象布尔isIdentical(EJBObject ejbobject)引发RemoteException
公共抽象void remove()抛出RemoteException,RemoveException
}
方法getEJBHome()返回对远程Home接口对象的引用。
方法getHandle()当前组件接口对象的句柄和远程主机接口的句柄一样,是序列化的,所以可以保存在本地或者通过RMI/IIOP协议传输给其他JVM上的客户,不需要JNDI查找调用主机接口的create方法。只需执行Handle.getEJBObject()方法来获取这个Bean实例的引用。
getPrimaryKey()方法一般用于实体Bean,如果在会话Bean中调用,会抛出java.rmi.RemoteException。
isIdentical()方法用于将当前引用的Bean实例与另一个Bean实例进行比较。