按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
存中删去。在Java 中,一个对象的生存时间也由客户的数量决定。若不再有对那个对象的引用,对象就会等
候垃圾收集器的处理。
Java 与 之间这种紧密的对应关系不仅使 Java 程序员可以方便地访问 特性,也使 Java 成为编写
代码的一种有效语言。 是与语言无关的,但 开发事实上采用的语言是 C++和 Visual Basic。同Java
相比,C++在进行 开发时显得更加强大,并可生成更有效的代码,只是它很难使用。Visual Basic 比
Java 简单得多,但它距离基础操作系统太远了,而且它的对象模型并未实现与 很好的对应(映射)关
系。Java 是两者之间一种很好的折衷方案。
接下来,让我们对 开发的一些关键问题进行讨论。编写Java/ 客户和服务器时,这些问题是首先需要
弄清楚的。
A。5。1 基础
是一种二进制规范,致力于实施可相互操作的对象。例如, 认为一个对象的二进制布局必须能够调用
另一个 对象里的服务。由于是对二进制布局的一种描述,所以只要某种语言能生成这样的一种布局,就
可通过它实现 对象。通常,程序员不必关注象这样的一些低级细节,因为编译器可自动生成正确的布
局。例如,假设您的程序是用 C++写的,那么大多数编译器都能生成符合 规范的一张虚拟函数表格。对
那些不生成可执行代码的语言,比如VB 和Java,在运行期则会自动挂接到。
库也提供了几个基本的函数,比如用于创建对象或查找系统中一个已注册 类的函数。
一个组件对象模型的基本目标包括:
■让对象调用其他对象里的服务
■允许新类型对象(或更新对象)无缝插入环境
第一点正是面向对象程序设计要解决的问题:我们有一个客户对象,它能向一个服务器对象发出请求。在这
种情况下,“客户”和“服务器”这两个术语是在常规意义上使用的,并非指一些特定的硬件配置。对于任
何面向对象的语言,第一个目标都是很容易达到的——只要您的代码是一个完整的代码块,同时实现了服务
器对象代码以及客户对象代码。若改变了客户和服务器对象相互间的沟通形式,只需简单地重新编译和链接
一遍即可。重新启动应用程序时,它就会自动采用组件的最新版本。
但假若应用程序由一些未在自己控制之下的组件对象构成,情况就会变得迥然有异——我们不能控制它们的
源码,而且它们的更新可能完全独立于我们的应用程序进行。例如,当我们在自己的程序里使用由其他厂商
开发的ActiveX 控件时,就会面临这一情况。控件会安装到我们的系统里,我们的程序能够(在运行期)定
位服务器代码,激活对象,同它建立链接,然后使用它。以后,我们可安装控件的新版本,我们的应用程序
应该仍然能够运行;即使在最糟的情况下,它也应礼貌地报告一条出错消息,比如“控件未找到”等等;一
般不会莫名其妙地挂起或死机。
在这些情况下,我们的组件是在独立的可执行代码文件里实现的:DLL 或 EXE。若服务器对象在一个独立的可
执行代码文件里实现,就需要由操作系统提供的一个标准方法,从而激活这些对象。当然,我们并不想在自
己的代码里使用DLL 或 EXE 的物理名称及位置,因为这些参数可能经常发生变化。此时,我们想使用的是由
操作系统维护的一些标识符。另外,我们的应用程序需要对服务器展示出来的服务进行的一个描述。下面这
两个小节将分别讨论这两个问题。
1。 GUID和注册表
采用结构化的整数值(长度为 128位)唯一性地标识系统中注册的 项目。这些数字的正式名称叫作
GUID (Globally Unique IDentifier,全局唯一标识符),可由特殊的工具生成。此外,这些数字可以保证
在“任何空间和时间”里独一无二,没有重复。在空间,是由于数字生成器会读取网卡的 ID号码;在时间,
是由于同时会用到系统的日期和时间。可用GUID 标识 类(此时叫作 CLSID)或者 接口(IID)。尽
管名字不同,但基本概念与二进制结构都是相同的。GUID 亦可在其他环境中使用,这里不再赘述。
GUID 以及相关的信息都保存在Windows 注册表中,或者说保存在“注册数据库”(Registration
Database )中。这是一种分级式的数据库,内建于操作系统中,容纳了与系统软硬件配置有关的大量信息。
对于,注册表会跟踪系统内安装的组件,比如它们的CLSID、实现它们的可执行文件的名字及位置以及其
他大量细节。其中一个比较重要的细节是组件的ProgID;ProgID 在概念上类似于GUID,因为它们都标识着
一个 组件。区别在于 GUID 是一个二进制的、通过算法生成的值。而 ProgID 则是由程序员定义的字串
值。ProgID 是随同一个CLSID 分配的。
我们说一个 组件已在系统内注册,最起码的一个条件就是它的 CLSID 和它的执行文件已存在于注册表中
662
…………………………………………………………Page 664……………………………………………………………
(ProgID 通常也已就位)。在后面的例子里,我们主要任务就是注册与使用 组件。
注册表的一项重要特点就是它作为客户和服务器对象之间的一个去耦层使用。利用注册表内保存的一些信
息,客户会激活服务器;其中一项信息是服务器执行模块的物理位置。若这个位置发生了变动,注册表内的
信息就会相应地更新。但这个更新过程对于客户来说是“透明”或者看不见的。后者只需直接使用ProgID 或
CLSID 即可。换句话说,注册表使服务器代码的位置透明成为了可能。随着D (分布式)的引入,在
本地机器上运行的一个服务器甚至可移到网络中的一台远程机器,整个过程甚至不会引起客户对它的丝毫注
意(大多数情况下如此)。
2。 类型库
由于 具有动态链接的能力,同时由于客户和服务器代码可以分开独立发展,所以客户随时都要动态侦测
由服务器展示出来的服务。这些服务是用“类型库”(Type Library)中一种二进制的、与语言无关的形式
描述的(就象接口和方法签名)。它既可以是一个独立的文件(通常采用。TLB 扩展名),也可以是链接到执
行程序内部的一种Win32 资源。运行期间,客户会利用类型库的信息调用服务器中的函数。
我们可以写一个Microsoft Interface Definition Language (微软接口定义语言,MIDL )源文件,用MIDL
编译器编译它,从而生成一个。TLB 文件。MIDL 语言的作用是对 类、接口以及方法进行描述。它在名称、
语法以及用途上都类似 OMB/CORBA IDL 。然而,Java 程序员不必使用MIDL 。后面还会讲到另一种不同的
Microsoft 工具,它能读入Java 类文件,并能生成一个类型库。
3。 :HRESULT 中的函数返回代码
由服务器展示出来的 函数会返回一个值,采用预先定义好的HRESULT 类型。HRESULT 代表一个包含了三
个字段的整数。这样便可使用多个失败和成功代码,同时还可以使用其他信息。由于 函数返回的是一个
HRESULT,所以不能用返回值从函数调用里取回原始数据。若必须返回数据,可传递指向一个内存区域的指
针,函数将在那个区域里填充数据。我们把这称为 “外部参数”。作为Java/ 程序员,我们不必过于关注
这个问题,因为虚拟机会帮助我们自动照管一切。这个问题将在后续的小节里讲述。
A。5。2 MS Java/ 集成
同C++/ 程序员相比,Microsoft Java 编译器、虚拟机以及各式各样的工具极大简化了Java/ 程序员
的工作。编译器有特殊的引导命令和包,可将 Java 类当作 类对待。但在大多数情况下,我们只需依赖
Microsoft JVM 为 提供的支持,同时利用两个有力的外部工具。
Microsoft Java Virtual Machine (JVM)在 和Java 对象