第九讲 JavaBean和RMI.docx
《第九讲 JavaBean和RMI.docx》由会员分享,可在线阅读,更多相关《第九讲 JavaBean和RMI.docx(33页珍藏版)》请在冰豆网上搜索。
第九讲JavaBean和RMI
【课前思考】
1.什么是JavaBean?
2.JavaBean和Java有什么关系?
3.JavaBean会有什么样的用途?
4.什么是RMI?
5.RMI技术会有什么样的特点?
6.什么是EJB?
7.EJB和JavaBean又有什么样的关系?
第九讲JavaBean和RMI
9.1JavaBean的基本概念
9.1.1JavaBean产生的背景介绍
软件业一直是计算机产业的核心,计算机刚问世的时候,计算机软件基本处于缓慢发展时期,那时候使用的计算机软件语言是与硬件紧密相关的机器语言,随后出现了汇编语言。
随着计算机日益介入到人们的生活中间,软件也相应的变得更加复杂。
于是以编程人员为中心的高级语言替代了计算机发展初期的低级语言,其中,50年代末和60年代初的FORTRAN语言的出现是一个变革,同时像BASIC和LISP这样的高级语言也相应的产生了,这些语言使得编程人员可以超脱于具体的硬件结构,使用更接近于实际问题领域的术语表达其设计思想。
但是另一方面,这种新出现的自由度使得不断复杂的应用程序需要有更加复杂的软件来实现。
软件工业自由度和复杂性的增加,软件开发队伍也不断膨胀,成本也不断提高。
软件工业也在不断的寻求成本低廉而又快速可靠的软件开发方法,所以在90年代末期,基于组件的软件开发的思想开始得到了普遍的重视和应用。
软件组件就是指可以进行独立分离、易于重复使用的软件部分。
JavaBean就是一种基于Java平台的软件组件思想。
JavaBean也是一种独立于平台和结构的应用程序编程接口(API)。
JavaBean保留了其他软件组件的技术精华,并增加了被其他软件组件技术忽略的技术特性,使得它成为完整的软件组件解决方案的基础,并在可移植的Java平台上方便地用于网络世界中。
其实你可以把组件理解成为童年时玩的积木,而把用组件搭起来的软件则可以理解成为你用积木搭的形状各异的作品。
这种比喻也许可以让你理解为什么用组件搭建应用程序会比其他方法制作应用程序更加稳定和快速。
因为软件的组件是可重用的,所以它肯定是经过了很多应用程序的测试,所以当你用它的时候出错的概率肯定比你自己重新写一个同样功能的模块的出错概率小。
而用组件搭建应用程序同时也会更快速,这很容易理解,就像你用积木搭一座桥比你自己用木头做一座桥要快一样。
JavaBean也是一个很成功的组件模型,如果你用过JBuilder,那么你肯定会受益于它所提供的许多方便的控件,而这些控件几乎都是JavaBean。
其实你已经不知不觉的在使用JavaBean了,只是你一直没有注意到而已。
9.1.2JavaBean基本概念
虽然JavaBean和Java之间已经有了明确的界限,但是在某些方面JavaBean和Java之间仍然存在很容易混淆的地方,比如说重用,Java语言也可以为用户创建可重用的对象,但它没有管理这些对象相互作用的规则或标准,用户可以使用在Java中预先建立好的对象,但这必须具有对象在代码层次上的接口的丰富知识。
而对于JavaBean,用户可以在应用程序构造器工具中使用各种JavaBean组件,而不需要编写任何代码。
这种同时使用多个组件而不考虑其初始化情况的功能是对当前Java模型的重要扩展,所以也可以说JavaBean是在组件技术上对Java语言的扩展。
如果真的要明确的定义,那么JavaBean的定义是:
JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作。
在上面的定义中,软件构造器可以是Web页面构造器、可视化应用程序构造器、GUI设计构造器或服务器应用程序构造器。
而JavaBean可以是简单的GUI要素,如按钮和滚动条;也可以是复杂的可视化软件组件,如数据库视图。
有些JavaBean是没有GUI表现形式的,但这些JavaBean仍然可以使用应用程序构造器可视化地进行组合,比如JBuilder上的很多控件其实也是没有GUI形式的,但是你仍然可以拖放它们以在你的应用程序里生成相应的代码。
一个JavaBean和一个JavaApplet很相似,是一个非常简单的遵循某种严格协议的Java类。
JavaBean具有Java语言的所有优点,比如跨平台等等,但它又是Java在组件技术方面的扩展,所以说很多方面它和Applet很像,Applet也具有Java语言的所有优点,同时也是Java在浏览器端程序方面的扩展。
其实它们都是严格遵循某种协议的Java类,它们的存在都离不开Java语言的强大支持。
9.1.3JavaBean的属性、事件和方法
从基本上来说,JavaBean可以看成是一个黑盒子,即只需要知道其功能而不必管其内部结构的软件设备。
黑盒子只介绍和定义其外部特征和与其他部分的接口,如按钮、窗口、颜色、形状等。
作为一个黑盒子的模型,以把JavaBean看成是用于接受事件和处理事件以便进行某个操作的组件建筑块。
一个JavaBean由3部分组成:
(1)属性(properties)
JavaBean提供了高层次的属性概念,属性在JavaBean中不只是传统的面向对象的概念里的属性,它同时还得到了属性读取和属性写入的API的支持。
属性值可以通过调用适当的bean方法进行。
比如,可能bean有一个名字属性,这个属性的值可能需要调用StringgetName()方法读取,而写入属性值可能要需要调用voidsetName(Stringstr)的方法。
每个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.4JavaBean的特征
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.5JavaBean特征实现的简介
1.属性
2.内省和定制
3.持续
4.事件
1.属性
Bean的属性描述其外观或者行为特征,如颜色、大小等。
属性可以在运行时通过get/set方法取得和设置。
最终用户可以通过特定属性的get/set方法对其进行改变。
例如,对于Bean的颜色属性,最终用户可以通过Bean提供的属性对话框改变这个颜色属性。
颜色的改变实际上是通过下面的方法实现的:
publicColorgetFillColor();
publicvoidSetFillColor(Colorc);
这种基本的get/set方法命名规则定义的属性叫做简单属性。
简单属性中有一类用boolean值表示的属性叫布尔属性。
JavaBeanAPI还支持索引属性,这种属性与传统Java编程中的数组非常类似。
索引属性包括几个数据类型相同的元素,这些元素可以通过一个整数索引值来访问,因此称为索引属性。
属性可以索引成支持一定范围的值,这种属性属于简单属性。
索引用int指定。
索引属性有4种访问方式,其数值数组可以一个元素访问,也可以整个数组访问:
publicvoidsetLabel(intindex,Stringlabel);
publicStringgetLabel(intindex);
publicvoidsetLabel(String[]labels);
publicString[]getLabels();
与标准的Java数组类似索引值可能会在索引属性数组的范围之外。
这时,用于操作索引属性的访问者方法一般是抛出一个ArrayIndexOutOfBoundsException运行环境异常,这个异常与标准Java数组索引超出范围时执行的行为相同。
与简单属性相对的是关联属性和限制属性。
这两种属性在运行或者设计时被修改后,可以自动地通知外部世界,或者有能力拒绝被设置为某个数值的属性。
关联属性在属性发生改变时向其他beans和容器发出通知。
关联属性在发生改变时产生一个PropertyChangeEvent事件,传递给所关联的注册了PropertyChangeListener的听众。
可以通过下述方法注册或撤销多路广播事件听众:
publicvoidaddPropertyChangeListener(PropertyChangeListenerl);
publicvoidremovePropertyChangeListener(PropertyChangeListenerl);
PropertyChangeListener是一个接口,当相关的外部部件需要与一个属性相关联时,它必须调用addPropertyChangeListener()方法提供一个合适的实现了PropertyChangeListener接口的对象。
PropertyChangeListener接口用于报告关联属性的修改,尤其是当一个关联属性值发生变化时,就调用所有注册的PropertyChangeListener接口上的propertyChange()方法。
这个方法接受一个PropertyChangeEvent对象,这个对象包含了关于要修改的特定属性的信息及其新值和旧值。
下图显示了关联属性是如何工作的:
上面的图中发生的主要事件就是从bean发送一个属性修改通知给一个监听器。
监听器必须先注册bean,然后才通过检查随通知发送来的PropertyChangeEvent对象决定修改了的特定属性。
JavaBeanAPI还支持另一种方法用于注册监听器与特定的关联属性。
如果一个bean开发者要在单个属性基础上提供监听器注册,他必须为每个这样的属性支持一对方法:
addListener()和removeListener()。
这对方法工作起来就像前面介绍的那对全局事件监听器注册方法,只是这两个方法是用于特定的属性。
下面的一个例子中定义了一个名为Name的关联属性的这两个方法:
publicvoidaddNameListener(PropertyChangeListenerl);
publicvoidremoveNameListener(PropertyChangeListenerl);
当bean外部相关部件要将其本身注册到Name属性上时,它只需简单地调用addNameListener()方法来注册它本身。
当Name属性修改时,会通过调用propertyChange()方法发送一个通知给事件监听器。
这种情况与前面介绍的一样,只是这里的监听器只接收关于Name属性的通知。
限制属性是内部验证的,如果不合格会被拒绝。
用户可以通过异常获知拒绝的属性。
限制属性用VetoableChangeListener接口验证改变。
可以用如下方法注册或撤销该接口:
publicvoidaddVetoableChangeListener(VetoableChangeListenerv);
publicvoidremoveVetoableChangeListener(VetoableChangeListenerv);
限制属性和关联属性的处理机制是很类似的,当属性的修改值到达监听器的时候,监听器可以通过抛出PropertyVetoException异常选择拒绝属性的修改。
如果抛出了一个异常,这个bean就要负责处理这个异常并恢复这个限制属性的原来的值。
与关联属性类似,限制属性也支持单个属性的事件监听方法。
下面是一个例子:
publicvoidaddNameListener(VetoableChangeListenerl);
publicvoidremoveNameListener(VetoableChangeListenerl);
2.内省和定制
Bean通常被开发成一般化的组件,由开发人员在建立应用程序时配置。
这是通过JavaBeansAPI伴随的两种Java技术实现的。
第一种是Java反映API,是一组用于透视类文件和显示其中的属性和方法的类。
第二种是Java串行化API,用于生成类的永久存储,包括其当前状态。
这两种技术用于使Beans可以用建立工具探索和显示,并修改和存放起来,供特定应用程序使用。
JavaBean的内省过程显示Bean的属性、方法和事件。
内省过程实际上很简单,如果有设置或取得属性类型的方法,则假设Bean有该属性,可以采用如下方法:
publicget();
publicvoidset(p);
如果只发现一个get/set方法,则确定PropertyName为只读或只写。
除了上述这种内置的内省和定制方法外,JavaBeanAPI还提供了显示的接口BeanInfo,用于Bean设计者显示Bean的属性、事件、方法和各种全局信息。
可以通过实现BeanInfo接口定义自己的Bean信息类:
publicclassmyBeanInfoimplementsBeanInfo..
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.2JavaBean开发简介
9.2.1一个简单的JavaBean例子
本小节将通过一个简单的Bean的构造说明建立Bean的一般过程。
通过本小节的介绍,我们可以了解怎样生成一个简单的Bean,编译并把它存到一个jar文件中去。
1.编写Bean的源程序SimpleBean.java
2.编译源程序
3.编写制作(nmake)文件
4.运行makefile文件
1.编写Bean的源程序SimpleBean.java如下:
importjava.awt.*;
importjava.io.Serializable;
publicclassSimpleBeanextendsCanvasimplementsSerializable
{
//该bean从java.awt.Canvas派生,所以具有了Canvas的所有属性和方法
publicSimpleBean(){
setSize(60,40);//设置该bean的尺寸
setBackground(Color.red);//设置该bean的背景颜色
}
}
SimpleBean从java.awt.Canvas组件派生,所以是一个可视化的bean,并且实现了java.io.Serializable接口,这个接口是所有Bean都必须实现的,因为SimpleBean具有Canvas的所有属性和方法,如背景色和组件尺寸等属性,并可以调用相应的方法设置这些属性。
2.编译源程序:
javacSimpleBean.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
jarcfm$(JARFILE)manifest.tmp*.class
@/bin/rmmanifest.tmp
#编译源程序
%.class:
%.java
exportCLASSPATH;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)
jarcfm$(JARFILE)< Name:
SimpleBean.class
Java-Bean:
True
<<
#将类打包,"Java-Bean:
True"可以使得类出现在ToolBox窗口中
.SUFFIXES:
.java.class
{sunw/demo/simple}.java{sunw/demo/simple}.class:
setCLASSPATH=.
javac$<
#清除中间文件
clean:
-delsunw/demo/simple/*.class
-del$(JARFILE)
4.运行makefile文件
对于UNIX,运行gnumakesimple.gmk
对于windows,运行nmake-fsimple.mk
会在当前目录下创建一个JAR文件,这个JAR文件里包含了这个bean的信息。
本小节我们完成了一个很典型的JavaBean,其实就是一个有一定特殊规则的Java类,它有一些特殊的地方比如要实现某些接口类,不过归根结底它还是一个Java类,它可以使用任何Java语言里提供的功能比如说继承于Canvas等。
而上面我们提供的makefile则可以作为模板,你以后要编写你自己的bean的makefile的时候只需要修改上面提供的makefile就可以了。
9.2.2使用这个JavaBean构造应用程序
在上一小节,我们已经做出了自己的一个JavaBean,那么,如何使用这个JavaBean呢,在这一节,我们将在一个JavaApplet中使用这个JavaBean。
1.编写SimpleBeanTest.java文件
2.编译这个文件
3.还需要编写testbean.html文件
4.用AppletViewer查看结果
1.编写SimpleBeanTest.java文件,源程序如下:
importjava.applet.*;
publicclassSimpleBeanTestextends