9.1 JavaBean的基本概念
9.1.1 JavaBean产生的背景介绍
软件业一直是计算机产业的核心,计算机刚问世的时候,计算机软件基本处于缓慢发展时期,那时候使用的计算机软件语言是与硬件紧密相关的机器语言,随后出现了汇编语言。随着计算机日益介入到人们的生活中间,软件也相应的变得更加复杂。于是以编程人员为中心的高级语言替代了计算机发展初期的低级语言,其中,50年代末和60年代初的FORTRAN语言的出现是一个变革,同时像BASIC和LISP这样的高级语言也相应的产生了,这些语言使得编程人员可以超脱于具体的硬件结构,使用更接近于实际问题领域的术语表达其设计思想。
但是另一方面,这种新出现的自由度使得不断复杂的应用程序需要有更加复杂的软件来实现。软件工业自由度和复杂性的增加,软件开发队伍也不断膨胀,成本也不断提高。软件工业也在不断的寻求成本低廉而又快速可靠的软件开发方法,所以在90年代末期,基于组件的软件开发的思想开始得到了普遍的重视和应用。
软件组件就是指可以进行独立分离、易于重复使用的软件部分。JavaBean就是一种基于Java平台的软件组件思想。JavaBean也是一种独立于平台和结构的应用程序编程接口(API)。JavaBean保留了其他软件组件的技术精华,并增加了被其他软件组件技术忽略的技术特性,使得它成为完整的软件组件解决方案的基础,并在可移植的Java平台上方便地用于网络世界中。
其实你可以把组件理解成为童年时玩的积木,而把用组件搭起来的软件则可以理解成为你用积木搭的形状各异的作品。这种比喻也许可以让你理解为什么用组件搭建应用程序会比其他方法制作应用程序更加稳定和快速。因为软件的组件是可重用的,所以它肯定是经过了很多应用程序的测试,所以当你用它的时候出错的概率肯定比你自己重新写一个同样功能的模块的出错概率小。而用组件搭建应用程序同时也会更快速,这很容易理解,就像你用积木搭一座桥比你自己用木头做一座桥要快一样。
JavaBean也是一个很成功的组件模型,如果你用过JBuilder,那么你肯定会受益于它所提供的许多方便的控件,而这些控件几乎都是JavaBean。其实你已经不知不觉的在使用JavaBean了,只是你一直没有注意到而已。
9.1.2 JavaBean基本概念
虽然JavaBean和Java之间已经有了明确的界限,但是在某些方面JavaBean和Java之间仍然存在很容易混淆的地方,比如说重用,Java语言也可以为用户创建可重用的对象,但它没有管理这些对象相互作用的规则或标准,用户可以使用在Java中预先建立好的对象,但这必须具有对象在代码层次上的接口的丰富知识。而对于JavaBean,用户可以在应用程序构造器工具中使用各种JavaBean组件,而不需要编写任何代码。这种同时使用多个组件而不考虑其初始化情况的功能是对当前Java模型的重要扩展,所以也可以说JavaBean是在组件技术上对Java语言的扩展。
如果真的要明确的定义,那么JavaBean的定义是:JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作。在上面的定义中,软件构造器可以是Web页面构造器、可视化应用程序构造器、GUI设计构造器或服务器应用程序构造器。而JavaBean可以是简单的GUI要素,如按钮和滚动条;也可以是复杂的可视化软件组件,如数据库视图。有些JavaBean是没有GUI表现形式的,但这些JavaBean仍然可以使用应用程序构造器可视化地进行组合,比如JBuilder上的很多控件其实也是没有GUI形式的,但是你仍然可以拖放它们以在你的应用程序里生成相应的代码。一个JavaBean和一个Java Applet很相似,是一个非常简单的遵循某种严格协议的Java类。
JavaBean具有Java语言的所有优点,比如跨平台等等,但它又是Java在组件技术方面的扩展,所以说很多方面它和Applet很像,Applet也具有Java语言的所有优点,同时也是Java在浏览器端程序方面的扩展。其实它们都是严格遵循某种协议的Java类,它们的存在都离不开Java语言的强大支持。
9.1.3 JavaBean的属性、事件和方法
从基本上来说,JavaBean可以看成是一个黑盒子,即只需要知道其功能而不必管其内部结构的软件设备。黑盒子只介绍和定义其外部特征和与其他部分的接口,如按钮、窗口、颜色、形状等。作为一个黑盒子的模型,以把JavaBean看成是用于接受事件和处理事件以便进行某个操作的组件建筑块。
一个JavaBean由3部分组成:
(1) 属性(properties)
JavaBean提供了高层次的属性概念,属性在JavaBean中不只是传统的面向对象的概念里的属性,它同时还得到了属性读取和属性写入的API的支持。属性值可以通过调用适当的bean方法进行。比如,可能bean有一个名字属性,这个属性的值可能需要调用String getName()方法读取,而写入属性值可能要需要调用void setName(String str)的方法。
每个JavaBean属性通常都应该遵循简单的方法命名规则,这样应用程序构造器工具和最终用户才能找到JavaBean提供的属性,然后查询或修改属性值,对bean进行操作。JavaBean还可以对属性值的改变作出及时的反应。比如一个显示当前时间的JavaBean,如果改变时钟的时区属性,则时钟会立即重画,显示当前指定时区的时间。
(2) 方法(method)
JavaBean中的方法就是通常的Java方法,它可以从其他组件或在脚本环境中调用。默认情况下,所有bean的公有方法都可以被外部调用,但bean一般只会引出其公有方法的一个子集。
由于JavaBean本身是Java对象,调用这个对象的方法是与其交互作用的唯一途径。JavaBean严格遵守面向对象的类设计逻辑,不让外部世界访问其任何字段(没有public字段)。这样,方法调用是接触Bean的唯一途径。
但是和普通类不同的是,对有些Bean来说,采用调用实例方法的低级机制并不是操作和使用Bean的主要途径。公开Bean方法在Bean操作中降为辅助地位,因为两个高级Bean特性--属性和事件是与Bean交互作用的更好方式。
因此Bean可以提供要让客户使用的public方法,但应当认识到,Bean设计人员希望看到绝大部分Bean的功能反映在属性和事件中,而不是在人工调用和各个方法中。
(3) 事件(event)
Bean与其他软件组件交流信息的主要方式是发送和接受事件。我们可以将bean的事件支持功能看作是集成电路中的输入输出引脚:工程师将引脚连接在一起组成系统,让组件进行通讯。有些引脚用于输入,有些引脚用于输出,相当于事件模型中的发送事件和接收事件。
事件为JavaBean组件提供了一种发送通知给其他组件的方法。在AWT事件模型中,一个事件源可以注册事件监听器对象。当事件源检测到发生了某种事件时,它将调用事件监听器对象中的一个适当的事件处理方法来处理这个事件。
由此可见,JavaBean确实也是普通的Java对象,只不过它遵循了一些特别的约定而已。
9.1.4 JavaBean的特征
JavaBean1.0指定的组件模型规定了Bean的如下特征:
(1)内省:使组件可以发表其支持的操作和属性的机制,也是支持在其他组件中(如Bean的开发工具)发现这种机制的机制。
(2)属性:在设计Bean时可以改变的外观和行为特征。开发工具通过对Bean进行内省来获知其属性,进而发布其属性。
(3)定制:Bean通过发布其属性使其可以在设计时被定制。有两种方法支持定制:通过使用Beans的属性编辑器,或者是使用更复杂Bean定制器。
(4)通信:Bean之间通过事件互相通信。开发工具可以检测一个Bean可以接收和引发的事件。
(5)持续:使Bean可以存储和恢复其状态。一个Bean的属性被修改以后,可以通过对象的持续化机制保存下来,并可以在需要的时候恢复。
你也许会好奇,这么多特性是如何在JavaBean里得到实现的呢?JavaBean借助了很多Java语言提供的功能和思想,下一节我们将讨论一下JavaBean的这些特征是如何实现的,这个稍微有点复杂,所以请你打起精神,继续我们的JavaBean之旅。
9.1.5 JavaBean特征实现的简介
1. 属性
2. 内省和定制
3. 持续
4. 事件
1. 属性
Bean的属性描述其外观或者行为特征,如颜色、大小等。属性可以在运行时通过get/set方法取得和设置。最终用户可以通过特定属性的get/set方法对其进行改变。例如,对于Bean的颜色属性,最终用户可以通过Bean提供的属性对话框改变这个颜色属性。颜色的改变实际上是通过下面的方法实现的:
public Color getFillColor();
public void SetFillColor(Color c);
这种基本的get/set方法命名规则定义的属性叫做简单属性。简单属性中有一类用boolean值表示的属性叫布尔属性。
JavaBean API还支持索引属性,这种属性与传统Java编程中的数组非常类似。索引属性包括几个数据类型相同的元素,这些元素可以通过一个整数索引值来访问,因此称为索引属性。属性可以索引成支持一定范围的值,这种属性属于简单属性。索引用int指定。索引属性有4种访问方式,其数值数组可以一个元素访问,也可以整个数组访问:
public void setLabel(int index,String label);
public String getLabel(int index);
public void setLabel(String []labels);
public String []getLabels();
与标准的Java数组类似索引值可能会在索引属性数组的范围之外。这时,用于操作索引属性的访问者方法一般是抛出一个ArrayIndexOutOfBoundsException运行环境异常,这个异常与标准Java数组索引超出范围时执行的行为相同。
与简单属性相对的是关联属性和限制属性。这两种属性在运行或者设计时被修改后,可以自动地通知外部世界,或者有能力拒绝被设置为某个数值的属性。关联属性在属性发生改变时向其他beans和容器发出通知。关联属性在发生改变时产生一个PropertyChangeEvent事件,传递给所关联的注册了PropertyChangeListener的听众。可以通过下述方法注册或撤销多路广播事件听众:
public void addPropertyChangeListener(PropertyChangeListener l);
public void removePropertyChangeListener(PropertyChangeListener l);
PropertyChangeListener是一个接口,当相关的外部部件需要与一个属性相关联时,它必须调用addPropertyChangeListener()方法提供一个合适的实现了PropertyChangeListener接口的对象。PropertyChangeListener接口用于报告关联属性的修改,尤其是当一个关联属性值发生变化时,就调用所有注册的PropertyChangeListener接口上的propertyChange()方法。这个方法接受一个PropertyChangeEvent对象,这个对象包含了关于要修改的特定属性的信息及其新值和旧值。下图显示了关联属性是如何工作的:
上面的图中发生的主要事件就是从bean发送一个属性修改通知给一个监听器。监听器必须先注册bean,然后才通过检查随通知发送来的PropertyChangeEvent对象决定修改了的特定属性。
JavaBean API还支持另一种方法用于注册监听器与特定的关联属性。如果一个bean开发者要在单个属性基础上提供监听器注册,他必须为每个这样的属性支持一对方法:add<propertyname>Listener()和remove</propertyname><pnropertyname>Listener()。这对方法工作起来就像前面介绍的那对全局事件监听器注册方法,只是这两个方法是用于特定的属性。下面的一个例子中定义了一个名为Name的关联属性的这两个方法:
public void addNameListener(PropertyChangeListener l);
public void removeNameListener(PropertyChangeListener l);</pnropertyname>
当bean外部相关部件要将其本身注册到Name属性上时,它只需简单地调用addNameListener()方法来注册它本身。当Name属性修改时,会通过调用propertyChange()方法发送一个通知给事件监听器。这种情况与前面介绍的一样,只是这里的监听器只接收关于Name属性的通知。
限制属性是内部验证的,如果不合格会被拒绝。用户可以通过异常获知拒绝的属性。限制属性用VetoableChangeListener接口验证改变。可以用如下方法注册或撤销该接口:
public void addVetoableChangeListener(VetoableChangeListener v);
public void removeVetoableChangeListener(VetoableChangeListener v);
限制属性和关联属性的处理机制是很类似的,当属性的修改值到达监听器的时候,监听器可以通过抛出PropertyVetoException异常选择拒绝属性的修改。如果抛出了一个异常,这个bean就要负责处理这个异常并恢复这个限制属性的原来的值。
与关联属性类似,限制属性也支持单个属性的事件监听方法。下面是一个例子:
public void addNameListener(VetoableChangeListener l);
public void removeNameListener(VetoableChangeListener l);
2. 内省和定制
Bean通常被开发成一般化的组件,由开发人员在建立应用程序时配置。这是通过JavaBeans API伴随的两种Java技术实现的。第一种是Java反映API,是一组用于透视类文件和显示其中的属性和方法的类。第二种是Java串行化API,用于生成类的永久存储,包括其当前状态。这两种技术用于使Beans可以用建立工具探索和显示,并修改和存放起来,供特定应用程序使用。
JavaBean的内省过程显示Bean的属性、方法和事件。内省过程实际上很简单,如果有设置或取得属性类型的方法,则假设Bean有该属性,可以采用如下方法:
public <propertytype>get</propertytype><propertyname>();
public void set</propertyname><propertyname>(</propertyname><propertytype> p);</propertytype>
如果只发现一个get/set方法,则确定PropertyName为只读或只写。
除了上述这种内置的内省和定制方法外,JavaBean API还提供了显示的接口BeanInfo,用于Bean设计者显示Bean的属性、事件、方法和各种全局信息。可以通过实现BeanInfo接口定义自己的Bean信息类:
public class myBeanInfo implements BeanInfo..
BeanInfo接口提供了一系列访问Bean信息的方法,Bean开发者还可以提供BeanInfo类用于定义Bean信息的专用描述文件。
3. 持续
JavaBean是依赖于状态的组件,状态可能因为运行时或开发时的一些动作而发生改变,当Bean的状态改变时,设计人员可以保存改变的状态,这种机制叫JavaBean的持续。
JavaBean状态的持续可以通过java对象的串行化机制自动保存,也可以由设计者通过定制其串行化控制Bean对象的状态的保存。
4. 事件
JavaBean通过传递事件在Bean之间通信。Bean用一个事件告诉另一个Bean采取一个动作或告诉其状态发生了改变。事件从源听众注册或发表并通过方法调用传递到一个或几个目标听众。
JavaBean的事件模型类似AWT的事件模型。JavaBean中的事件模型是用事件源和事件目标定义的。事件源就是事件的启动者,由它触发一个或多个事件目标。事件源和事件目标建立一组方法,用于事件源调动事件听众。
本节介绍了JavaBean的基本概念和JavaBean的一些内部机制,现在你应该已经知道JavaBean是个什么东西,而且你对JavaBean内部遵循的规范和一些实现的细节也有了一定的了解,比如你应该知道JavaBean有什么特征,
也应该对其中的机制有一定的了解。不过你肯定还有疑惑,因为你还没有见过一个JavaBean的代码究竟是怎样的,也就是你开始想编写JavaBean了,那么,让我们继续下一节。
9.2 JavaBean开发简介
9.2.1一个简单的JavaBean例子
本小节将通过一个简单的Bean的构造说明建立Bean的一般过程。通过本小节的介绍,我们可以了解怎样生成一个简单的Bean,编译并把它存到一个jar文件中去。
1. 编写Bean的源程序SimpleBean.java
2. 编译源程序
3. 编写制作(nmake)文件
4. 运行makefile文件
1. 编写Bean的源程序SimpleBean.java如下:
import java.awt.*;
import java.io.Serializable;
public class SimpleBean extends Canvas implements Serializable
{
//该bean从java.awt.Canvas派生,所以具有了Canvas的所有属性和方法
public SimpleBean(){
setSize(60,40); //设置该bean的尺寸
setBackground(Color.red); //设置该bean的背景颜色
}
}
SimpleBean从java.awt.Canvas组件派生,所以是一个可视化的bean,并且实现了java.io.Serializable接口,这个接口是所有Bean都必须实现的,因为SimpleBean具有Canvas的所有属性和方法,如背景色和组件尺寸等属性,并可以调用相应的方法设置这些属性。
2. 编译源程序:
javac SimpleBean.java产生字节码文件SimpleBean.class。
3. 编写制作(nmake)文件
这个nmake文件会编译这个SimpleBean组件并会产生一个JAR文件。将编写好的makefile文件存储为simpe.gmk(UNIX)或simple.mk(windows),并与你的SimpleBean.class放在同一个目录下,nmake文件清单如下:
#gmumake文件
CLASSFILES= SimpleBean.class
JARFILE= SimpleBean.jar
all: $(JARFILE)
# 创建一个带有适当说明文件(manifest)的JAR文件
$(JARFILE): $(CLASSFILES) $(DATAFILES)
echo "Name: SimpleBean.class" >> manifest.tmp
echo "Java-Bean: True" >> manifest.tmp
jar cfm $(JARFILE) manifest.tmp *.class
@/bin/rm manifest.tmp
# 编译源程序
%.class: %.java
export CLASSPATH; CLASSPATH=. ; \
javac $<
#删除产生的中间文件
clean:
/bin/rm -f *.class
/bin/rm -f $(JARFILE)
# nmake 文件
CLASSFILES= simplebean.class
JARFILE= simplebean.jar
all: $(JARFILE)
# 创建一个带有适当说明文件(manifest)的JAR文件
$(JARFILE): $(CLASSFILES) $(DATAFILES)
jar cfm $(JARFILE) <<manifest.tmp *.class<br=""> Name: SimpleBean.class
Java-Bean: True
<<
#将类打包,"Java-Bean:True"可以使得类出现在ToolBox窗口中
.SUFFIXES: .java .class
{sunw\demo\simple}.java{sunw\demo\simple}.class :
set CLASSPATH=.
javac $<
#清除中间文件
clean:
-del sunw\demo\simple\*.class
-del $(JARFILE)
4. 运行makefile文件
对于UNIX,运行gnumake simple.gmk
对于windows,运行nmake -f simple.mk
会在当前目录下创建一个JAR文件,这个JAR文件里包含了这个bean的信息。
本小节我们完成了一个很典型的JavaBean,其实就是一个有一定特殊规则的Java类,它有一些特殊的地方比如要实现某些接口类,不过归根结底它还是一个Java类,它可以使用任何Java语言里提供的功能比如说继承于Canvas等。而上面我们提供的makefile则可以作为模板,你以后要编写你自己的bean的makefile的时候只需要修改上面提供的makefile就可以了。
9.2.2 使用这个JavaBean构造应用程序
在上一小节,我们已经做出了自己的一个JavaBean,那么,如何使用这个JavaBean呢,在这一节,我们将在一个Java Applet中使用这个JavaBean。
1. 编写SimpleBeanTest.java文件
2. 编译这个文件
3. 还需要编写testbean.html文件
4. 用AppletViewer查看结果
1. 编写SimpleBeanTest.java文件,源程序如下:
import java.applet.*;
public class SimpleBeanTest extends Applet
{
public void init()
{
add ( new SimpleBean()); //在该Applet中使用SimpleBean
}
}
2. 编译这个文件,如下所示:
javac SimpleBeanTest.java
3. 还需要编写testbean.html文件,源程序如下:
<applet code="SimpleBeanTest" height="250" width="250">
</applet>
4. 用AppletViewer查看结果,如下所示:
AppletViewer testbean.html
如果你看到下图所示的结果,那么显然,你已经成功的将你的bean应用到这个Applet中了。如果结果没有出来,别着急,看看你的所有文件是不是都在一个目录下面。
本小节我们将bean应用到一个Applet中了,你开始感到bean的强大了吧,如果我们有很多bean,那么搭建应用程序就很方便了,只需要根据不同的功能要求使用不同的bean就行了,而我们只需要搭建应用程序的框架就可以了,这看起来还真像是童年的积木游戏。
9.2.3 JavaBean的开发工具简介
如果你用过Visual Basic或Delphi,你会觉得一个好的集成开发环境可以给程序员带来极大的方便。在编写简单的bean的时候我们不会感到麻烦,但是如果我们需要开发具有复杂的结构的bean,那么,一个好的集成开发环境显然会是我们的工作变得更加简单。而幸运的是,我们不仅有很多bean可以用,也有很多bean的开发工具可以用。下面着重介绍几个常用的bean开发工具。
1. Borland公司的JBuilder
2. IBM公司的Visual Age for Java
3. SunSoft公司的Java Studio
1. Borland公司的JBuilder
使用JBuilder,开发者可以使用任何包括在这个产品中的或是从第三方供应商购买的JavaBean组件迅速地开发出应用程序,也可以使用JBuilder的可视化设计工具和wizard创建自己的可复用的JavaBean组件。JBuilder含有功能强大的JavaBean数据库组件,它可以满足创建与数据库有关的应用程序的需求。另外,JBuilder提供了Java优化工具集为专业Java开发者提供了综合的、高性能的开发解决方案。JBuilder的基于组件开发环境的几个主要子系统,包括组件设计器和双向工具引擎,都是使用JavaBean内置于Java中的。
关于JBuilder的更多信息,可以访问Borland公司的Web站点:
http://www.borland.com/jbuilder
2. IBM公司的Visual Age for Java
IBM的Visual Age for Java的发布使得客户/服务器系统的Internet应用程序的实现成为现实。这个工具将Java的快速开发环境与可视化编程结合在一起。Visual Age for Java是一个创建可与Java兼容的应用程序、applet和JavaBean组件的编程环境,它使得开发者可以将注意力集中在应用程序的逻辑设计上。Visual Age for Java可以帮助开发者实现许多应用程序中经常需要的任务,如通讯代码、在企业级上进行Web连接以及用户接口代码的创建。
关于Visual Age for Java的更详细的信息可以查看Web站点:
http://www.software.ibm.com/ad/vajava
3. SunSoft公司的Java Studio
Java Studio是一个可视化组装工具,一个"所见即所得"的HTML创作工具和一个完全使用Java编写的可重复使用的组件开发工具。Java Studio使用的JavaBean技术包含了一个丰富而强壮的商业组件集合,包括图表、曲线以及通过窗体和电子表格等支持的数据库访问和操作。此外,还包括用于创建网络软件辅助组件。辅助组件包括电子表格、白板和聊天组件。
Java Studio的web网址位于:
http://www.sun.com/studio/
本小节介绍了几个常用的JavaBean集成开发环境,但其实它们的功能很强大,其实它们都是Java的集成开发环境,不仅仅能搭建JavaBean,还能搭建与Java有关的应用程序和Applet等等Java相关的产品,你不妨试试看哪个开发环境更适合你,当然,如果你认为用UltraEdit+JDK来开发Java程序是件很开心的事情,那么你可以不去理会这些庞大的集成开发环境。
9.2.4 使用BeanBox测试JavaBean
BDK(Beans Developmen Kit)是Sun公司发布的Beans开发工具箱,它与JDK配合使用,可以生成使用Bean事件模型的Beans。BDK的使用依赖于JDK。BeanBox是BDK中自带的一个用于测试Beans的工具,可以用它可视地管理Beans的属性和事件。BeanBox并不是一个建立Beans的工具,它只是一个测试工具,我们可以通过它来了解Beans。
在BDK的安装目录下,有一个子目录beanbox,该目录下有beanbox的执行程序,在UNIX平台下运行run.sh,在windows平台下运行run.bat,即可启动BeanBox应用程序。
启动BeanBox后,将出现三个窗口:ToolBox窗口(左),BeanBox窗口(中)和属性编辑窗口(右),如图所示:
ToolBox窗口中包含了在BeanBox中可以使用的Beans。可以从该窗口选取需要的Bean,把它拖放到BeanBox窗口。
BeanBox窗口可以用来可视化地联系各个Bean,定义Bean的外观,怎样与其他Bean交互。BeanBox窗口本身是BeanBox这个Bean的一个实例。为了将一个Bean放到BeanBox窗口中,从ToolBox窗口的Bean图标或名称中选择一个Bean,然后在Bean要放的位置中央单击鼠标将Bean放到BeanBox窗口,这时Bean就会在指定的位置显示出来。要从几个Bean中选择一个,只要用鼠标单击该bean即可。被选中的Bean将具有一个黑白相间的边框。
属性编辑窗口显示当前选中的Bean的属性,也可以在该窗口中修改Bean的属性。
下面我们用BeanBox来测试我们前面完成的SimpleBean是不是一个符合规范的JavaBean。
1. 将JAR文件载入ToolBox。
选择菜单项File|LoadJar,这时将出现一个文件选择框。寻找到SimpleBean.jar所在的位置,然后选择该文件,之后SimpleBean将出现在ToolBox的底部(当BeanBox启动时,BDK所在目录的jars子目录中的JAR文件中包含的所有Bean将自动载入ToolBox中)。
2. 选取一个SimpleBean的实例到BeanBox容器中去。
在ToolBox中用鼠标点击SimpleBean选项,这是鼠标将变为十字型,移动鼠标到BeanBox窗口中某一处按下,之后SimpleBean将以一个具有阴影线边框的彩色矩形框出现。边框表示SimpleBean被选中,SimpleBean的属性将出现在属性编辑窗口中。
由于SimpleBean是从Canvas派生出来的,所以可以像普通组件一样改变大小和位置。
3. 检查SimpleBean的属性和事件
在属性编辑窗口中显示了当前Bean的属性。选中SimpleBean时,将显示4个属性:前景色、背景色、字体、名称。我们没有在SimpleBean中显示地定义属性,这些属性都是从Canvas中继承过来的。在每个属性处点击鼠标都将弹出一个属性编辑对话框。可以在属性编辑对话框中对属性进行修改。
Beans通过发送和接受事件与其他Bean进行通信。为了获知SimpleBean可以发送哪些类型的事件,可以选择Edit|Event菜单项。这时将出现一个事件列表,这些事件就是该Bean可以发送的事件类型。
能够被BeanBox加载的JAR文件里包含的都是标准的JavaBean,BeanBox可以对JavaBean的属性进行编辑,也可以编辑JavaBean之间的事件,让不同的JavaBean协同工作,同时BeanBox很小,是一个很方便的工具,我们可以用BeanBox来检验我们编写的JavaBean是不是符合规范。
9.3 RMI的基本概念和编程简介
9.3.1 RMI的基本概念
Java RMI(Remote Method Invocation)--Java的远程方法调用是Java所特有的分布式计算技术,它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象的方法,从而使Java编程人员可以方便地在网络环境中作分布式计算。面向对象设计要求每个任务由最适合该任务的对象执行,RMI将这个概念更深入了一步,使任务可以在最适合该任务的机器上完成。
RMI定义了一组远程接口,可以用于生成远程对象。客户机可以象调用本地对象的方法一样用相同的语法调用远程对象。RMI API提供的类和方法可以处理所有访问远程方法的基础通信和参数引用要求的串行化。
远程方法调用类似于Sun公司1985年提出的远程过程调用(RPC)特征。RPC也要求串行化参数和返回数值数据,但由于没有涉及对象,情况比较简单。Sun开发了外部数据表示(XDR)系统,支持数据串行化。RPC和RMI之间的一个重要差别是RPC用快速而不够可靠的UDP协议,RMI用低速而可靠的TCP/IP协议。
远程方法调用(RMI)和CORBA都是分布式计算技术,在进行分布式时各有其优缺点,为了有助于了解RMI的特点和用途,有必要讨论一下CORBA和RMI的区别。
CORBA(Common Object Request Broker Architecture)是OMG的Object Management Architecture(对象管理结构),它是面向对象的分布式系统建立所依据的标准。CORBA被设计成一个能供所有编程语言使用的一个开放性说明,就是说一个机器上的Java客户可以要求另一个用SmallTalk或C++的机器服务。正是由于这种语言的独立性使得CORBA这么灵活和吸引人。为了适应语言独立性,CORBA采用了非常通用的标准作为其接口。在不同的语言中,远程调用、签名和对象的引入有各自不同的定义,所以CORBA必须尽可能的中立和开放。正是这种通用性是CORBA的一个弱点。当开发人员都采用CORBA时,他们要用一种新的标准定义语言接口,它要求开发者学习新的编程接口,从而减小了远程模型的透明性。
RMI是为仅在Java对Java的分布式计算中而开发的。远程调用的标准是为了Java和应用Java的自然Java签名和调用而开发的,这使得RMI对Java的开发者相当透明而且易于实现。RMI用Java语言紧密集成从而同CORBA相比能够提供非常好的容错能力及对异常的处理。尽管Java的RMI标准不像CORBA那样语言独立,但Java本身是一个独立的平台,这就使RMI在跨平台的分布软件开发中是一个很好的选择。
RMI是Java语言在分布式计算上的基本模型,很多Java的分布式系统,包括我们本章要涉及的EJB,都是建立在RMI的思想上的。
9.3.2 RMI系统的一般结构
RMI系统包括3层,端头/框架层(Stubs/Skeletons)、远程应用层(Remote Reference Layer)和传送层(Transport),如图所示:
客户机调用远程方法时,请求用客户机的端头调用。客户机引用端头作为远程机上对象的代表。上图所示的所有基础功能在客户机上都看不到。端头代码由rmic编译器长生,并用远程引用层(RRL)将方法调用请求传递到服务器对象。
1) 端头(Stub)
端头就是代表远程对象的客户机方代理,定义远程对象版本支持的所有接口。端头在客户机上运行的程序像本地对象一样引用,从客户机来看与本地对象相似,它还保持与服务器方对象的连接。客户机方的远程应用层返回端头的调动流。客户方的RRL用调用流与服务器方的RRL通信。端头将参数数据串行化,将串行化的数据传递到调动流。
执行完远程方法调用后,RRL将串行化的返回值送回端头,负责反串行化。
2) 框架(Skeleton)
框架是与服务器方RRL接口的服务器方构件。框架接受客户机方RRL的方法调用请求。服务器方RRL要反调动发送到远程方法的任何变元。然后框架调用服务器方的实际对象实现。框架还负责接收来自远程对象的返回值并将其调动到调动流中。
3) 远程引用层(Remote Reference Layer)
远程引用层(RRL)负责维护不与具体端头或框架模型相关的独立应用协议。这个灵活性使RRL的改变不会影响另外两层。RRL涉及低级传送接口,负责向端头和框架层提供流。
RRL通过传送层用客户机方面和服务器方构件通信。客户机方构件包含远程服务器的特定信息。这个信息传递到服务器方构件,因此只依赖于服务方RRL。服务器方RRL负责引用语法和处理这些语法之后再向框架发送远程方法调用。客户机和服务器方构件之间的通信由传送层处理。
4) 传送层(Transport Layer)
传送层负责建立并维护客户机和服务器之间的连接。传送层包括4个抽象:
端点(endpoint)抽象用于引用包含Java虚拟机的地址空间,是具体传送接口的引用。
通道(channel)抽象是两个地址空间之间的通路。这个通路负责管理客户机和服务器之间的各种连接。
连接(connection)抽象是客户机和服务器之间数据(变元和返回值)传送的抽象。
传送(transport)抽象负责建立本地地址空间和远程端点之间的通道。传送抽象还负责接收到包含抽象的地址空间的输入连接。
传送层建立连接,管理现有连接和处理地址空间中的远程对象。
传送层接收客户机方RRL请求时,它寻找请求的远程对象的RMI服务器,然后传送层建立到这个服务器的接插连接。接着,传送层将建立的连接传递到客户机RRL上并将远程对象的引用加入内部表。这时客户机即连接到服务器。
传送层监视连接的"活性"。如果经过较长时间连接毫无动静,则传送层负责关掉这个连接。
RMI的分层结构不仅在概念上显得很清晰和合理,而且也给我们开发RMI应用程序提供了极大的方便,设想一下,如果我们需要去了解传送层的细节,那么,RMI的应用程序的开发将会是一件很艰巨的任务。幸好,我们没有必要那么做,RMI的分层结构是我们可以在高层进行开发而不必要去理会底层的细节,其实,开发RMI应用程序和开发普通的Java应用程序几乎没有什么区别。
9.3.3使用RMI构造分布式应用系统
RMI应用程序通常由两个独立的程序构成:一个server和一个client。一个典型的server应用程序创建一些远程对象,使它们可被引用,并等待客户端调用这些远程对象的方法。一个典型的client应用程序得到server上的一个或多个远程对象的远程引用,并调用这些对象的方法。RMI提供了server和client通信和传递信息的机制。这样的应用程序叫做一个分布式对象应用程序。
分布式对象应用程序需要定位远程对象:应用程序可以使用两种机制之一来获得远程对象的引用。应用程序可以使用RMI的命名工具rmiregistry来注册它的远程对象,或者象进行一般操作一样传递和返回远程对象的引用。
和远程对象通信:远程对象之间的通信细节由RMI来处理。对程序员来说,远程通信就像一个标准的Java方法调用。
装载被传递对象的类字节码:因为RMI允许调用者向远程对象传递对象,所以它提供了传递数据和装载一个对象代码的必要机制。
下图描述了一个使用注册机制获得一个远程对象引用的RMI分布式应用程序。Server方调用注册器将一个远程对象和一个名字联系起来。Client方在Server的注册器中通过名字寻找远程对象并调用其方法。该图也显示了RMI系统使用一个现有web server来装载类字节码,在需要时在server和client之间传输字节码。
RMI的一个重要而独特的特性是它能动态下载一个在接收者的虚拟机中未定义的对象类的字节码(或简单代码)。一个对象的类型和行为,这些原来只能在一个单一的虚拟机中可以得到的信息,可以被传递给另一个可能是远程的虚拟机。RMI将对象连同其真实的类型一起传递,所以当这些对象被传递给另一个虚拟机时其行为不发生改变。这就允许将新类型引入一个远程的虚拟机,从而动态扩展一个应用程序的行为。
像其他应用程序一样,一个使用Java RMI的分布式应用程序也由接口和类组成。接口中定义一些方法,类实现接口中定义的方法,并定义一些其他的方法。在一个分布式应用程序中,一些实现需要驻留在不同的虚拟机上。具有可以跨虚拟机调用的方法的对象叫做远程对象。一个对象通过实现一个远程接口成为远程对象,它具有如下特征:
1) 一个远程接口由java.rmi.Remote派生。
2) 接口中的每个方法都要声明抛出java.rmi.RemoteException,除了 其他特殊的例外之外。
当对象从一个虚拟机传递给另一个虚拟机时,RMI对远程对象的处理与非远程对象是不相同的。对于远程对象,RMI传递给接收方虚拟机一个远程端头,而不是一个对象的拷贝。端头作为远程对象的本地标识或代理,对于调用方来说,是一个远程引用。调用方调用本地端头的一个方法,由本地端头负责处理对远程对象的方法调用。
一个远程对象的端头实现了与远程对象实现的相同的接口。这就允许一个端头可以被转换为远程对象所实现的任意一个接口。这也意味着只有定义在远程接口中的方法才可以在接收方虚拟机上被调用。
当你使用RMI来开发一个分布式应用时,需要遵守下面的步骤:
1) 设计和实现你的分布式应用的组件。
首先,决定应用程序的结构,哪些组件是本地对象,哪些应该可以远程访问。这个步骤包括:
定义远程接口:一个远程接口定义了可以被客户端远程调用的方法。客户端针对远程接口编程,而不是针对实现这些接口的类。设计这样的接口的一部分工作取决于作为这些方法的参数和返回值的本地对象。如果还没有这样的接口和类的存在,就需要自己定义。
实现远程对象:远程对象必须实现一个或多个远程接口。远程对象类可能包括其他接口(本地的或远程的)和方法(仅在本地可得到的)的实现。如果有本地类作为这些方法的参数或返回值,这些类也必须被实现。
实现客户端:使用远程对象的客户可以在远程接口被定义后的任何时候实现,包括远程对象被展开后。
2) 编译源程序并生成端头。
这是一个两步操作过程。第一步,使用Javac编译器来编译源文件,其中包含了远程接口及其实现部分、server类和client类。第二步,使用rmic编译器来生成远程对象的端头。RMI使用一个远程对象的端头类来作为客户端的代理,从而使客户端可以同一个特定的远程对象通信。
3) 使得类可以通过网络访问。
这一步使一切与远程接口有关的类文件、端头、其他任意的需要下载到客户方的类可以通过一个web server访问。
4) 启动应用程序。
启动应用程序包括运行RMI远程对象注册程序,服务器,客户端。
用RMI来构造分布式应用系统是不是很简单的一件事情?的确,RMI使我们可以自己编写分布式的应用系统,在没有RMI之前这种事情是难于想象的。
9.3.4 一个简单的RMI的例子
一个虽然简单但是完整的RMI分布式应用程序的例子,该程序由两部分组成;包括远程对象的server方和调用server方的远程方法sayHello()获得字符串"Hello World"并输出该字符串的client方。
1. 构造一个远程接口Hello
2. 完成server方程序,定义HelloImpl类实现Hello接口
3. 完成client方程序
1. 构造一个远程接口Hello:
package hello;
public interface Hello extends java.rmi.Remote {
//rmi应用程序必须继承自java.rmi.Remote
String sayHello() throws java.rmi.RemoteException ;
//定义可以远程调用的接口
}
2. 完成server方程序,定义HelloImpl类实现Hello接口:
package hello;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class HelloImpl extends UnicastRemoteObject implements Hello
//实现Hello接口
{
private String name;
public HelloImpl (String s ) throws java.rmi.RemoteException{
super(); //调用父类的构造函数
name = s;
}
public String sayHello() throws RemoteException {
return "Hello world!"; //实现Hello接口定义的方法
}
public static void main ( String args [])
{
System.setSecurityManager ( new RMISecurityManager() );
//设置RMI程序需要的安全策略
try
{
HelloImpl obj = new HelloImpl("HelloServer");
//生成一个HelloImpl的实例
Naming.rebind("HelloServer", obj);
//将这个实例绑定到一个名字上
System.out.println("HelloImpl created and bound in the registry to the name HelloServer");
} catch (Exception e)
{
System.out.println("HelloImpl.main: an exception occured:");
e.printStackTrace(); //产生异常的话,打印出出错信息
}
}
}
server方生成一个远程对象并和一个可和客户对话的名称"HelloServer"绑定。Client端可以根据该名称寻找相应的远程对象,进而调用其远程方法。
3. 完成client方程序
package hello;
import java.rmi.*; public class HelloClient
{
public static void main(String args[])
{
System.setSecurityManager(new RMISecurityManager() );
//设置RMI需要的安全策略
try
{
Hello obj = (Hello) Naming.lookup("HelloServer");
//从服务端获得一个Hello的远程对象
String message = obj.sayHello();
//远程调用Hello的方法
System.out.println(message);
//将输出结果打印
} catch (Exception e)
{
System.out.println("Hello client : an exception occured");
e.printStackTrace(); //若有异常,输出异常信息
}
}
}
client利用java.rmi包中的Naming类的lookup()方法获得远程对象obj,然后调用其远程方法sayHello()获得字符串"Hello World",并输出到屏幕上。
要运行这几个程序,还有一些工作要做,这几个程序的文件名为Hello.java、HelloImpl.java、HelloClient.java,它们都被放置在的的d:\hello目录下,在windows下,你需要在命令窗口中如此运行它们:
1. Set CLASSPATH = %CLASSPATH%;d:\
2. 在d:\hello下编译源代码:
javac -d .. *.java
3. 在生成端头和框架模块,首先把目录切换回d:\
rmic -d . hello.HelloImpl
4. 在d:\下运行RMI远程对象注册程序
start rmiregistry
5. 在d:\下运行服务器程序
java -Djava.security.policy=my.policy hello.HelloImpl
6. 在d:\下运行客户端程序
java -Djava.security.policy=my.policy hello.HelloClient
其中上面的步骤中5和6出现的my.policy是一个文件,这个文件和Java的安全机制有关,在这个程序中我们不需要安全限制,所以我们把权限设为都可以访问。my.policy如下:
grant {
permission java.security.AllPermission;
};
你一定要记得设置这个文件,否则RMI将出"拒绝访问"的错误。如果你想了解Java其他的安全机制,那么可以参考Java里有关security的资料。
RMI属于Java高级技术的一种,通过本小节的学习,你应该已经对RMI有了一定的了解,分布式计算是一个很重要的技术,而Java在分布式计算方面有着很好的前景,以RMI为基础,Java将在分布式计算方面大有作为。
9.4 EJB简介
9.4.1 EJB出现的背景
EJB的出现对Java技术是一个很大的推动,因为EJB主要是面向企业级应用的,这使得Java有了企业级应用的方向。同样,EJB也是建立在Java语言上的,和JavaBean,Java Applet一样,它也是遵守一定规范的Java程序,只不过这是个复杂的规范。
传统的分布式应用程序都是基于Client/Server结构的,而近年来人们发现基于Client/Server结构的应用程序有很多缺点,比如:如果客户端的代码需要改变,那么所有机器上的客户端程序都要重新安装;如果某台机器有了不可修复的损坏,那么得去别的机器上重新安装客户端软件才能够使用。而基于Browser/Server结构的应用程序就没有以上的缺点了,我们可以使用任何一台有浏览器的机器来工作,而因为所有的程序逻辑都在服务器端,所以服务器端的代码变动不需要作为客户端的浏览器再做任何工作。
由于Browser/Server结构的这些优势,近年来关于Browser/Server的程序开发模式有了很多的研究和实践。而因为Browser没有办法表示复杂的程序逻辑,所以在表示界面的Browser和存储介质数据库之间必须还有一层结构,这层结构负责表示复杂的程序逻辑。这就是我们所说的服务器端构件,在Brower/Server结构中,我们的工作就是开发服务器端构件,但是开发服务器端构件是很麻烦的工作。因为服务器端构件必须接受很多客户端的请求,因此它必须具有多线程和事务处理等能力,而这些也成为服务器端构件开发的难点所在。
98年3月在San Francisco召开的JavaOne98开发者大会上,SUN公司正式发布了业界期待以久的EJB1.0版(Enterprise JavaBean 1.0)规范说明,在众多的大公司和开发人员中引起了巨大的反应,这标志着用Java开发服务器端构件和搭建企业级应用系统将变得更加简单。现在EJB2.0版已经发布,而相应的EJB产品也已经有很多了,像WebLogic公司的WebLogic,IBM公司的WebSphere,Inprise公司的Inprise Application Server等,都是很成功的产品。
9.4.2 EJB的概要
事实上EJB是Java在企业级应用的规范,所以EJB还是比较复杂的,EJB只是组件的规范,而为了让EJB跑起来还需要很多其他的东西,比如说容器,应用程序服务器等,这些都是和EJB紧密联系在一起的,而因为EJB一般用于Web应用中,所以还需要一个Web服务器,而EJB的客户端也可以是任何的Java程序,比如Applet、Servlet等等,所以EJB只是企业级应用平台中的一部分,而这个企业级应用平台就是Sun的J2EE(Java 2 Enterprise Edition)。而上面我们提到的Weblogic,Websphere其实都是符合J2EE的企业级应用平台。
EJB规范说明定义了Java的服务器端构件模型,目前已有很多可供使用的、由第三方供应商提供的、用于客户机端的构件,但用于服务器端的构件还不多,由于服务器端构件很缺乏或很难构造,因此基本上每一个开发人员还是不得不从头开始构造服务器体系结构,这是一个很糟糕的结果。EJB的出现恰恰是为了解决这个问题,EJB方法扩充了Java的客户端构件模型JavaBeans以及支持服务器端应用系统的开发,在EJB规范说明中,服务器中的很多功能由EJB容器提供,开发人员可以集中精力于应用系统的核心功能上。采用EJB技术可以大大减轻开发服务器端应用系统的工作量,因此EJB规范说明一经发布,立即引起许多开发人员的极大兴趣。
Sun公司发布的文档中对EJB的定义是:EJB是用于开发和部署多层结构的、分布式的、面向对象的Java应用系统的跨平台的构件体系结构。采用EJB可以使得开发商业应用系统变得容易,应用系统可以在一个支持EJB的环境中开发,开发完之后部署在其他的EJB环境中,随着需求的改变,应用系统可以不加修改地迁移到其他功能更强、更复杂的服务器上。
EJB简化了多层体系结构应用系统的开发过程。在分布式应用系统的开发中,采用多层体系结构的方法有很多优点,如增加了应用系统的可伸缩性、可靠性、灵活性等。因为服务器端构件可以根据应用需求加以修改,且构件在网络中的位置和应用无关,因此系统管理员可以很容易重新配置系统的负载。多层体系结构非常适合于大数据量的商业事务系统,特别是在基于Web的应用中,需要多层体系结构支持瘦客户机及浏览器的快速Applet下载,目前越来越多的系统开始采用多层体系结构的方法,所谓的多层结构,可以用下图来帮助理解:
在多层结构中,数据库算是一层,客户端算一层,而客户端和数据库之间统称为N-2层,N-2层主要是表示程序的逻辑。EJB的作用就是在这N-2层里面负责表示程序的逻辑和提供访问数据库的接口。EJB分为两类,一类是实体Bean(Entity Bean),这种EJB和数据库中的表有一一对应的关系,可以在数据改变的时候自动更新表里的内容。还有一类是对话Bean(Session Bean),这种EJB用于和客户端交互,代表了程序的逻辑,我们可以用这两种EJB来方便的构建自己的多层系统。
EJB把Java的"write once, run anywhere"思想提到了一个新的高度,服务器端构件在构件执行系统内执行,规范说明定义了构件执行系统所需要的服务,遵从EJB规范说明开发的构件可以在任何一个支持EJB的系统中执行。EJB其实是在容器里执行的,Sun公司也发布了EJB容器的规范,EJB可以在任何符合规范的容器中运行,容器其实就是给EJB提供服务的,比如说EJB需要的事务处理,多线程和安全机制等服务。
9.4.3 EJB的软构件模型简介
JavaBean也是构件,只不过它不是服务器端的构件,在构件中我们称JavaBean是轻量级的,而EJB是重量级的。如果你想了解一些构件的知识,那么可以参考构件方面的书籍和资料。
软构件模型的思想是创建可重用的构件并将其组合到容器中以得到新的应用系统,构件模型定义了构件的基本体系结构、构件界面的结构、和其他构件及容器相互作用的机制等。利用构件模型的规范说明,构件开发人员开发那些实现了应用程序逻辑的构件,而应用系统开发人员把这些预先开发好的构件组合成应用系统,这些应用系统也可以作为新的构件。软构建模型思想已经在软件开发界迅速流行,因为它可以达到以下这些目的:重用、高层开发、通过工具进行自动化开发、简化开发过程等。JavaBeans、EJB、COM/DCOM等都是软构件模型的例子。
有两种类型的软构件模型--客户端构件模型和服务器端构件模型。客户端构件模型如JavaBeans是专门用于处理程序的表示(presentation)及用户界面问题的;服务器端构件模型如EJB则向面向事务的中间件提供基础设施。
服务器端构件模型把构件模型的开发和中间件联系在一起。企业级应用的中间件以其复杂性著称,它不仅涉及到应用逻辑、并发性和伸缩性问题,也涉及到如何把不兼容的系统组合在一起的问题。服务器端构件模型解决了中间件开发的复杂性问题,它使得中间件开发人员集中于应用系统的逻辑部分,而不用处理同步、可伸缩性、事务集成、网络、分布式对象框架等一些分布式应用系统中存在的复杂问题。EJB构件模型如下图所示:
EJB构件模型给开发者提供了一下的支持:
1. 构件包含应用程序逻辑
2. 可重用的构件
3. 可伸缩性
4. 资源管理
5. 事务支持
6. 并发性管理
这些支持为服务器端构件的开发者提供了很大的方便,使得开发服务器端构件不再是一件很艰巨的任务。
9.4.4 EJB和其他技术的关系
1.EJB和JavaBean的关系
2.EJB和RMI的关系
3.EJB和网络计算的关系
1.EJB和JavaBean的关系
很多人往往把JavaBean和EJB混淆起来,JavaBean提供了基于构件的开发机制,一般JavaBeans是可视化的构件,也有一些JavaBeans是非可视化的,JavaBeans可以在多个应用系统中重用,一个标准的JavaBeans是一个客户端构件,在运行时不能被其他客户机程序存取或操作,但客户端的JavaBeans容器可以根据JavaBeans的属性、方法、事件的定义在设计或运行时对JavaBeans进行操作,JavaBeans不一定要用于Client/Server结构的系统。
EJB没有用户界面,完全位于服务器端,EJB可以多个JavaBean组成,规范说明详细说明了EJB容器需要满足的需求以及如何和EJB构件相互协作。EJB可以和远程客户端程序通信,并提供一定的功能,根据规范说明,EJB是Client/Server系统的一部分,如果不和客户端程序交互,EJB一般不执行具体的功能。EJB和JavaBean的一个重要区别是EJB提供了网路功能。
2.EJB和RMI的关系
EJB是分布式的组件,它支持远程调用。而EJB的这些网络特性是建立在RMI之上的,可以说,RMI是EJB网络特性的基石。
因为EJB是分布式的,所以如何定位一个EJB也是需要解决的问题,而这个问题和RMI里如何定位一个对象是一样的,EJB也用了RMI registry的思想,EJB里的JNDI(Java Naming and Directory Interface)也提供了注册一个对象的服务,已经注册了的对象可以很容易的被找到。这和RMI的registry的想法和功能上是一样的。
越深入EJB,你就会看到越多的RMI的影子。
3. EJB和网络计算的关系
由Beans构造的应用程序可以根据用户的需求分解成不同的构件,根据用户当前所需要的功能提供相关的构件,并随着用户新的需求随时下载新的构件,而用户没有用到其功能的构件可以驻留在服务器上,这就是网络计算所倡导的概念。
很多人并没有完全理解Java的概念,他们认为为了在一个客户端上运行Java程序,需要把一个庞大的、可能达几兆字节的Java应用程序一次性通过网络传输到客户端,事实上,这也是一些开发人员计划用Java改写旧的应用系统时易犯的错误。
在网络计算环境中利用Java的最好途径是由EJB提供服务端的构件,而由JavaBeans提供客户端的构件,两者结合在一起,将会使应用系统的搭建更为简单和快速。
只有把Java应用于服务器端的应用系统才能真正体现Java的威力,EJB是Java的服务器端构件模型,该模型保证开发出来的构件可以被部署在任何支持EJB规范说明的系统中,既使该系统是由不同的开发商提供的。采用EJB可以提高开发人员的生产率,构件开发人员和应用开发人员不需要实现系统中的一些复杂的逻辑结构,因为构件的容器已提供对这些服务的自动管理和控制,采用EJB开发的应用系统不用修改就可以从一个服务器迁移到另一个功能更强的服务器上。
总之,EJB技术将使得Java在企业计算中的地位得到加强,为基于Java的应用系统提供了一个框架,和目前的许多系统和模型相比,EJB具有许多优越性,种种迹象表明,EJB有可能成为分布式应用