zoukankan      html  css  js  c++  java
  • Mozilla研究—组件的创建过程

    Mozilla研究—组件的创建过程

     

    转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

    作者联系方式:Li XianJing <xianjimli at hotmail dot com>

    更新时间:2007-3-6

     

    mozilla是一个以浏览器为中心的软件平台,它在我们平台中占有重要地位。我们用它来实现WEB浏览器、WAP浏览器、邮件系统、电子书和帮助阅读器等应用程序。为此,我最近花了不少时间去阅读mozilla的代码和文档,我将写一系列的BLOG作为笔记,供有需要的朋友参考。本文介绍一下组件的创建过程。

     

    在《设计模式》一书中,作者把创建模式放在了该书的最前面,我想这一定是经过深思熟虑之后才决定的。试想,如果没有创建模式,接口的使用者必须要知道接口的具体实现,才能创建并使用它,那么接口的实现可能就要遍布整个系统了。如果是这样,那还能算是分离了接口与实现吗,还能算是针对接口编程吗?答案是否定的,所以创建模式尽管很简单,但它却是针对接口编程必要的手段。

     

    而在组件对象模型(COM)中大量使用了创建模式中的工厂模式。在XPCOM中,几乎所有组件都是通过工厂(Factory)来创建的。一个组件可以实现多个接口,一个Factory可以创建多个接口,所以通常一个组件只要实现一个Factory接口就够了,而不必为每个接口实现一个Factory。

     

    MSCOM的Factory接口叫作IClassFactory。记得当时有人说,这个名字取得不好。原因是IClassFactory生产的是对象而不是类,所以正确的名字应该叫IObjectFactory。呵,这倒是很有道理的。

     

    在介绍mozilla的组件创建过程之前,让我们先回忆一下MSCOM组件的创建过程,这对理解XPCOM组件的创建过程也是有帮助的。

     

    对于以动态库形式提供的MSCOM组件,必须export出下面这些函数:

    1.       DllGetClassObject 用来查询组件内的接口。

    2.       DllRegisterServer 向系统注册组件。

    3.       DllUnregisterServer 向系统注销组件。

    4.       DllCanUnloadNow 判断是否可以安全卸载组件。

     

    为了让客户可以使用自己,组件首先要把自己注册到系统中去。注册过程实际上就是向注册表中写入一些信息,让客户可以找到组件对应的动态库。然后客户通过系统API(如CoCreateInstance)创建来组件的实例,而CoCreateInstance等API先从注册表找到该组件的动态库,再调用动态库DllGetClassObject函数查询到IClassFactory接口,最后通过IClassFactory去创建组件的实例。

     

    mozilla中,XPCOM组件的创建与MSCOM组件的创建类似。这里的模块(Module)是一个物理实体(通常是动态库或JS),一个模块(Module)内可以封装多个组件,而每个组件内又可以实现多个接口。

     

    模块(Module)必须对外exportNSGetModule函数,该函数的功能是用来得到nsIModule接口的。nsIModule接口的主要函数如下:

    1.         GetClassObject用来查询组件内的接口。对应MSCOM的DllGetClassObject函数。

    2.         RegisterSelf向系统注册组件。对应MSCOM的DllRegisterServer函数。

    3.         UnregisterSelf向系统注销组件。对应MSCOM的DllUnregisterServer函数。

    4.         CanUnload判断是否可以安全卸载组件。对应MSCOM的DllCanUnloadNow函数。

     

    mozilla实现了一套宏,一个通用的Module(nsGenericModule)和一个通用的Factory(nsGenericFactory),在它们的帮助下,模块只要实现一个nsModuleComponentInfo结构就行了,这大大简化了开发的繁杂度。nsModuleComponentInfo的成员仍然比较多,幸好通常只要提供mDescription、mCID、mContractID和mConstructor几个成员就行了。

     

    nsGenericFactory 实现了nsIFactory接口,它只是对nsModuleComponentInfo的一个包装。NsIFactory的功能和MSCOM中的IClassFactory差不多,它需要提供下列接口函数:

    1.         CreateInstance 创建指定接口的实例。

    2.         LockFactory 加锁/解锁工厂。

     

    有了以上的背景知识,mozilla的组件创建过程就不难理解了:

    1.         mozilla调用NSGetModule获取IModule接口。(初始化时)

    2.         mozilla调用IModule接口的RegisterSelf函数,向组件管理器注册组件。(初始化时)

    3.         通过组件管理器查找组件的nsIFactory接口,然后通过组件的nsIFactory接口创建组件。

     

    这样一来,组件的使用者和实现者之间耦合就降到最低了,两者独立变化而互不影响。

     

    值得注意的是,在XPCOM中,组件的创建有两种方式:

    1.         创建实例(CreateInstance)。这是普通的创建方式,每次都调用Factory::CreateInstance来创建新的实例。

    2.         获取服务(GetService)。服务(Service)一词容易让人误解(我开始以为是跨进程的调用呢),其实这里的服务就是一个单件,也就是说该组件只有一个实例存在。获取服务时,组件管理器发现如果先前已经创建过该组件的实例,就直接返回先前的实例,否则调用Factory::CreateInstance创建组件的实例,并保存该实例的引用以备后面再使用。

     

    无论是以创建实例还是以获取服务的方式创建,对组件本身的实现没有太大的影响。只是如果按获取服务的方式创建,而且该服务可能在多线程环境下使用,那么组件要自己实现加锁保护。

     

    ~~end~~

     

  • 相关阅读:
    poj 2312 Battle City
    poj 2002 Squares
    poj 3641 Pseudoprime numbers
    poj 3580 SuperMemo
    poj 3281 Dining
    poj 3259 Wormholes
    poj 3080 Blue Jeans
    poj 3070 Fibonacci
    poj 2887 Big String
    poj 2631 Roads in the North
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167750.html
Copyright © 2011-2022 走看看