Java 版 (精华区)
发信人: zhangyan (电梯吃人啊), 信区: Java
标 题: EJB 编程模型
发信站: 哈工大紫丁香 (2001年05月18日17:53:51 星期五), 站内信件
发信人: SecretPower (梧桐雨@爱之箭), 信区: Java
标 题: EJB的编程模型
发信站: 武汉白云黄鹤站 (2001年05月18日14:09:07 星期五), 站内信件
第二部分:EJB 编程模型
Ken Nordby
软件工程师,IBM
2000 年 7 月
本文的第二部分说明创建 Enterprise JavaBean 组件所需的 Java 接口和类的作用。
除了对 bean 类本身进行编码外,EJB 开发人员还必须为 bean 定义一个本地接口和一
个远程接口。这些接口的实现类通常由容器生成,因此部署 EJB 组件是开发人员和 EJ
B 容器的合作行为。第二部分还区分了 enterprise bean 的两种主要类型,即会话 be
an 和实体 bean,并说明了 EJB 容器和 EJB 服务器之间的关系。
enterprise bean 的编程模型的三个关键特征是:面向对象、对象的分布式和使用代理
对象。由于此编程模型使用 Java 技术,因此它在本质上就是面向对象的。此模型也是
分布式的,这是指 bean 在理论上是位置透明的。根据 Enterprise JavaBeans (EJB)
规范,“一般说来,EJB 类和 EJB 容器的实际位置对客户机是透明的。”在客户机想要
访问 EJB 组件时使用代理对象。bean 本身对于客户机是不可访问的,对 bean 方法的
访问则由 helper 类提供。
接口、委托和代理
当 Java 程序员编写一个 Enterprise JavaBeans 组件时,他们所创建的类必须实现一
个 EJB 接口,并且它必须包含一个名为 ejbCreate() 的方法。一个 EJB 接口 -- 例如
SessionBean 接口 -- 指定了一些方法,它们包括以下各项:
ejbActivate()
ejbPassivate()
ejbRemove()
setSessionContext()
ejbActivate() 和 ejbPassivate() 方法通知一个 bean,管理该 bean 的容器组件正在
主动和被动之间切换 bean 的状态(这通常是指在内存中还是交换到磁盘)。ejbRemov
e() 方法使 bean 知道它已被从容器中删除。setSessionContext() 方法使 bean 与一
个上下文对象相关联,此上下文对象是为了便于 bean 与其容器进行通信。
ejbCreate() 方法并不是从零做起创建 enterprise bean 的。当客户机想要创建新的
enterprise bean 时,bean 的容器将调用这个 bean 的类的 newInstance() 方法,来
实例化新的 bean 对象。然后容器调用 setSessionContext() 方法来建立上下文对象,
用于与 bean 进行通信。最后,容器调用新 bean 中的 ejbCreate() 方法。像 ejbCre
ate()、ejbActivate() 和 ejbPassivate() 这样的方法有时称为对象生存周期方法,以
区别于业务逻辑方法。
当开发人员设计一个新的 EJB 组件时,编写组成 enterprise bean 类的代码本身是不
够的。EJB 程序员还必须编写两个将由 helper 类使用的 Java 接口。这些强制性接口
必须扩展标准的 EJBObject 和 EJBHome 接口,而这两个接口则都是 java.rmi.Remote
marker 接口的扩展。扩展标准 EJBObject 接口的接口被称为 enterprise bean 的远
程接口,它指定在 bean 自身中定义的业务方法。当应用程序调用 enterprise bean 中
的业务方法时,应用程序并不访问 bean 本身。实际上,方法调用被传递给实现 EJBOb
ject 接口扩展的那个对象。这种做法称为委托,它是 EJB 体系结构中的一个设计要点
:
“客户机从来不直接访问 enterprise bean 类的实例。客户机总是使用 enterprise b
ean 的远程接口来访问 enterprise bean 的实例。实现 enterprise bean 的远程接口
的类由容器提供。此类所实现的分布式对象称为 EJB 对象。”(Enterprise JavaBeans
Specification 1.0)
bean 对 EJBObject 接口的扩展称为其远程接口,而实现远程接口的对象则称为 EJB 对
象。
enterprise bean 还必须具有本地接口。此接口是标准 EJBHome 接口的扩展。实现 be
an 的本地接口的对象称为本地对象。本地对象包含一个 create() 方法,此方法由应用
程序调用,而应用程序则必须创建一个 bean 实例。本地对象中的 create() 方法创建
一个新的 EJB 对象。它并不直接创建新的 enterprise bean 实例,因为不允许直接访
问 bean。
EJB 对象和本地对象充当 bean 对象的代理,因为它们代表 bean 接收方法调用。EJB
对象主要为 bean 业务方法充当代理;本地对象主要为 bean 生存周期方法充当代理。
为 EJB 组件使用 create() 方法并不一定要实例化新的 bean。容器确定如何最好地满
足创建请求,对于某些类型的 bean,它可以重用现有的实例:
“客户机使用会话 bean 本地接口上的 create 和 remove 方法。虽然客户机以为它正
在控制着 EJB 实例的生存周期,但是,是容器在处理 create 和 remove 调用,而不一
定要创建和删除 EJB 实例。在客户机和...实例之间不存在固定的映射。容器只是将客
户机的工作委托给任何一个方法已经就绪的可用实例而已。”(Enterprise JavaBeans
Specification 1.0)
创建新的 bean 实例受容器的控制,并可以与客户机发布 create() 方法异步。
当创建一个 EJB 组件时,开发人员负责定义 EJBObject 接口和 EJBHome 接口,但是无
需编写实现这些接口的类的代码。EJB 容器软件组件自动创建这些类。
下面的代码段说明客户机应用程序可能怎样使用称为 CartBean 的 enterprise bean 来
进行在线购物:
CartHome cartHome = javax.rmi.PortableRemoteObject.narrow(
initialContext.lookup("applications/shopping_cart"), CartHome.class);
Cart cart = cartHome.create();
cart.addItem(item29);
cart.addItem(item67);
cart.addItem(item91);
cart.purchase();
cart.remove();
CartHome 是实现本地接口的类(EJBHome 接口的扩展)。Cart 是实现远程接口的类(
EJBObject 接口的扩展)。当客户机调用应用程序方法(如 addItem() 和 purchase()
)时,它们是在 cart 对象上调用的,此对象接着将这些方法的执行委托给 bean 自身
。enterprise bean 的功能是通过其代理 EJB 对象(即 cart)来获得的。如果多台客
户机同时访问 cart bean,将会发生什么事情呢?Enterprise bean 开发人员无需编写
代码来支持并发访问。并发性由 EJB 容器支持。
下图说明各 EJB 对象之间的关系:
服务器和容器
EJB 体系结构包括 EJB 服务器和 EJB 容器两个概念。EJB 服务器充当一种组件执行系
统,正如 EJB 白皮书中所述:
“Enterprise JavaBeans 规范为每个支持完全可移植性的 Java 应用程序服务器定义了
一个标准模型。任何厂商都可以使用此模型来实现对 Enterprise JavaBeans 组件的支
持。多种系统(如 TP 监视器、CORBA 运行时系统、COM 运行时系统、数据库系统、We
b 服务器系统或其它基于服务器的运行时系统)都可以调整到能够支持可移植的 Enter
prise JavaBeans 组件。”(Thomas, Enterprise JavaBeans Technology: Server Com
ponent Model for the Java Platform)
EJB 服务器为使用 EJB 组件的应用程序提供操作环境,并供应所有必需的服务,来支持
EJB 体系结构。打包 EJB 服务器软件并没有预先规定的方式。一种方法是将它作为一
项功能增强包括到应用程序服务器中,这就是在 IBM WebSphere Application Server,
Advanced Edition, Version 2.0 中采用的方法。
EJB 组件并不在 EJB 服务器的顶部直接执行。一个称为 EJB 容器的中间软件组件在 E
JB 服务器环境中运行,从而又为这些 bean 自身提供操作环境。EJB 容器对 EJB 应用
程序是完全透明的,但是在支持 bean 操作方面起着关键性的作用。
为了使 enterprise bean 能充当可重用的软件组件,它们对特定的服务器或平台功能不
能有内建的相关性。服务器端功能的几种常见类型已经被从 bean 设计中“分离出去”
,而将此功能的责任转移给了容器组件。例如,容器将被用来接管安全性、并发性、事
务处理、交换到辅助存储器和其它服务的责任,从而使 bean 免受服务器相关性的制约
,并将按业务逻辑来优化,而不是按服务逻辑来优化。
EJB 白皮书这样描述容器的作用:
“EJB 容器管理部署于其中的 enterprise bean。客户机应用程序并不直接与 enterpr
ise bean 进行交互。相反,客户机应用程序通过由容器生成的两个封装接口( EJB Ho
me 接口和 EJB Object 接口)与 enterprise bean 进行交互。当客户机使用封装接口
调用各种操作时,容器截获每个方法调用,并插入管理服务。”(Thomas, Enterprise
JavaBeans Technology: Server Component Model for the Java Platform)
可以期望 EJB 容器软件一般都会随 EJB 服务器软件一起提供,尽管规范允许分离这些
组件。除了提供对运行时服务(如事务处理和安全性)的访问以外,还期望 EJB 容器包
括各种必要工具,来支持 enterprise bean 的安装、操作和管理。例如,需要有工具解
释 EJB jar 文件的内容,有工具生成数据库访问,来获得容器提供的持久性,有工具监
视正在运行的 bean 的行为,以及实现安全性等。
Bean 风格
EJB 组件分为两种主要类别 -- 会话 bean 和实体 bean。根据 bean 处理状态、事务和
持久性的方式这些类别还可以进一步细分。会话 bean 通常具有以下属性:
代表单个客户机执行
可以是事务性的
可以更新共享数据库中的数据
生存期相对较短
其生存期通常就是客户机的生存期
任何持久性数据都由 bean 管理
可以依容器的判断予以删除
会在 EJB 服务器失败时被删除
实体 bean 通常具有以下属性:
代表数据库中的数据
是事务性的
允许多个用户共同访问
可以长期存在
持久性数据可以由容器管理
在 EJB 服务器失败后能继续生存
EJB 规范对会话 bean 和实体 bean 的说明如下:
“对于客户机,会话 enterprise bean 是一种非持久性的对象,它实现某些在服务器上
运行的业务逻辑。想像一个会话对象的一种方式是:会话对象是运行在服务器上的客户
机程序的逻辑扩展。会话对象不在多台客户机之间共享。
“对于客户机,实体 enterprise bean 是一种持久性对象,它代表一个存储在持久性存
储器(例如,一个数据库)中的实体的对象视图,或者是一个由现有企业应用程序实现
的实体。”(Enterprise JavaBeans Specification 1.0)
用一种粗略的说法,会话 bean 代表这样的操作,它检索或存储数据以满足用户请求;
而实体 bean 则代表一种数据集,可以访问这些数据集来满足用户请求。
会话 bean
最简单的一种 Enterprise JavaBeans 组件就是无状态的会话 bean。因为这些 bean 没
有可以区分它们的状态,所有的实例都是完全相同的。容器管理无状态会话 bean 的生
存周期,其方式是通过创建足够数目的此种 bean 来适应客户机工作负荷,并在不需要
它们时将其删除。钝化,即将闲置的 bean 写到磁盘上,不用于无状态的会话。要调用
bean,客户机程序调用本地接口中的 standard create() 方法,尽管此操作不一定导
致实例化新的 bean 实例。容器可以选择将客户机请求发送给现有的对象。反之,容器
则可以按它的选择创建新的实例,且独立于由客户机发布的 create() 方法。
在 EJB 本地对象上发布的 create() 调用返回一个对 EJB 对象的引用,这个 EJB 对象
代表 enterprise bean。一旦客户机有了 EJB 对象引用,它就可以将业务方法发布到
EJB 对象上,容器随之会将这些方法委托给 bean 自身。负责管理会话 bean 的容器组
件无需推断会话 bean 是否是无状态的。会话 bean 是无状态的还是有状态的在安装时
声明。
如果会话 bean 在方法调用之间保留状态信息,则它是有状态的。通过调用 ejbPassiv
ate() 方法,容器可以依其判断将有状态会话 bean 钝化,或写到辅助存储器中。EJB
规范并不要求容器在钝化 bean 时使用 Java 串行化协议,但是它们必须提供等价的功
能。当容器决定将一个非活动的会话 bean 交换回到内存中时,它会取消被动 bean 的
串行化,并调用 ejbActivate() 方法。有状态会话 bean 的开发人员负责确保状态数据
是可串行化的。在集群的应用程序服务器环境中实现有状态会话 bean 时务必要小心,
因为并不是所有的服务器都支持集群的有状态会话 bean 的同步化。
有状态会话 bean 可以是事务性的。通过使用 javax.transaction.UserTransaction 接
口中的方法,如 begin()、commit() 和 rollback(),bean 可以控制事务;通过实现
javax.ejb.SessionSynchronization 接口,bean 可以接收有关事务状态的通知。EJB
容器无需推断哪些 bean 需要事务支持;UserTransaction 接口仅可用于那些在安装时
被标记为事务性的 bean。
实体 bean
实体 bean 在体系结构上与会话 bean 类似,但它们提供对企业数据的访问,而不是支
持用户会话。一个实体 bean 可以支持多个并发用户,而容器则使访问和事务同步化。
实体 bean 还具有支持本地对象中的 finder 方法的主键。知道实体 bean 的主键的客
户机可以通过调用本地对象上的 findBy PrimaryKey() 方法获得对象引用。与会话 be
an 不同,实体 bean 的本地对象除了具有 create 方法外还具有 finder 方法。
持久性是实体 bean 的一个基本属性。EJB 规范允许两种形式的实体持久性:bean 管理
的持久性和容器管理的持久性。对于代表关系数据库中的数据的实体 bean,bean 对持
久性的管理意味着,对数据库访问的调用是直接编写在企业 bean 的方法中的(使用 J
DBC 或 SQLJ)。这种方法是直截了当的,但它降低了可移植性。容器对持久性的管理意
味着 bean 不受数据库调用的影响。在安装时告知容器有关 bean 数据所需的持久性,
而容器负责生成实现持久性的代码。这种方法允许 bean 的可移植性更高,甚至达到持
久性可使用不同数据源的程度。然而,此方法要求容器中要有复杂功能。
当实体 bean 对象与 EJB 对象相关联时,前者处于就绪状态;否则将认为它们处于共享
状态。当客户机调用 EJB 对象中的方法时,容器查找关联的实体 bean 的实例(如果存
在的话),或者从共享状态中传送出一个实例。处于就绪状态的实体 bean 可以接收到
通过委托从客户机传播给它们的业务方法调用。它们还可以在容器请求时执行 ejbLoad
() 和 ejbStore() 方法。load 方法和 store 方法旨在维持实体 bean 和基础数据存储
之间数据的一致性。
实体 bean 支持多个用户并发地访问数据。EJB 规范声明,维持数据完整性是容器的责
任:
--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 天外飞仙]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.718毫秒