📄 208002.htm
字号:
<html><body><span id=Layer1><a name=208002><font color=#3e70d7 face=arial size=5><b>COM+基础概念</span><span id=Layer2></b></font><p><font size=2 color=#3c3c3c face=arial>若要掌控COM runtime提供的服务首要工作便是了解一些其它的事情。在本章中,我将假设你至少已阅读过</span><span id=Layer3> <a target='_new' href=201.htm#>第一</span><span id=Layer4></a> 、</span><span id=Layer5> <a target='_new' href=205.htm#>五</span><span id=Layer6></a> 、</span><span id=Layer7> <a target='_new' href=206.htm#>六</span><span id=Layer8></a> 与</span><span id=Layer9> <a target='_new' href=207.htm#>七章</span><span id=Layer10></a> 的内容,因此你已了解Windows 2000分散式环境的基础概念,包含COM、ADO与DTC。在进一步了解COM runtime提供给应用程式使用的服务之前,还有许多的概念需要介绍。</span><span id=Layer11></font></p><font color=#3e72d7 face=arial size=4><b>COM+ 应用程式</span><span id=Layer12></b></font><p><font size=2 color=#3c3c3c face=arial>若要使用COM+,则商业逻辑必须撰写成一个或多个(通常是多个)in-process的COM元件,这也就是说,写成包装成DLL的COM类别。一旦这些元件建立後,便可使用元件服务(Component Services)管理工具将其分组成COM+应用程式。(所谓的COM+应用程式就是指MTS中所称的套件(package),不过不要被这个术语搞混了∶COM+应用程式只提供完整的叁层式应用程式之中间层。)在特定COM+应用程式中的所有元件都会执行在相同的行程中,因此将元件分组成应用程式的方式便决定行程的结构。</span><span id=Layer13></font></p><p><font size=2 color=#3c3c3c face=arial>一个COM+应用程式是一组in-process的COM 元件</span><span id=Layer14></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个COM+应用程式是一组in-process的COM 元件</span><span id=Layer15></font></p><hr><p><font size=2 color=#3c3c3c face=arial>两种最重要的COM+应用程式便是伺服器应用程式(Server Application)与程式库应用程式(Library Application)。这两个应用程式主要的不同点在於,每一个伺服器应用程式分别执行在自己的行程中,而从程式库应用程式中建立的元件将会执行在建立物件的客户端之行程内。如图8-2所示,对於单独的Windows 2000机器来说同时执行多个伺服器应用程式是完全合法的。每个伺服器应用程式将会执行在自己的行程中,而每个行程将会有自己的一份COM runtime复本。因为身为COM+应用程式的元件都必需是DLL,因此必需要有某个EXE档案,以提供一个行程让DLL执行。通常这个EXE的选择是随着Windows 2000出货的简单行程,称为COM+代理程序(COM+ Surrogate)。本章没有提供任何图片阐述代理程序,通常在EXE被要求宿驻(host)某些COM+应用程式的DLL时会自动地载入。</span><span id=Layer16></font></p><p><font size=2 color=#3c3c3c face=arial>COM+支援伺服器应用程式与程式库应用程式</span><span id=Layer17></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>COM+支援伺服器应用程式与程式库应用程式</span><span id=Layer18></font></p><hr><p><font size=2 color=#3c3c3c face=arial>在图中,Server Application 1包含元件A与B,已载入到同一个行程中,而客户端将可从COM runtime的其中一个实例 (instance)存取它的物件。Server Application 2包含元件C与 D已载入另一个行程,还有一个包含元件E与F的程式库应用程式已载入相同的行程中。有两个客户端呼叫其中一个应用程式或两个应用程式中的物件之method,所有的呼叫动作都会透过第二个行程中的COM runtime进行。</span><span id=Layer19></font></p><br><center><a target=_new href=imagesh/8-2.gif><img border=0 src='imagesl/8-2.gif'></a></center></span><span id=Layer20><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图 8-2</span><span id=Layer21> </b></font>每个COM+伺服器应用程式都拥有自己的行程,而程式库应用程式则否。</span><span id=Layer22></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>一旦一个COM元件成为COM+应用程式的一部份,这个元件就被视为一个已设定元件(configured component)。回顾一下在一个COM+应用程式中所有的元件都必需撰写成in-process伺服器,意思是每一个设定的元件都必需为一个DLL。在Windows 2000平台上,一个非隶属於COM+应用程式一部份的COM元件称为未设定元件(unconfigured component),也就是在</span><span id=Layer23> <a target='_new' href=205.htm#>第五章</span><span id=Layer24></a> 提及的部份。一个元件最多仅可以是一台特定机器上某个COM+应用程式的一部份,因此关於元件属於哪一个应用程式就不会暧昧不明了。</span><span id=Layer25></font></p><p><font size=2 color=#3c3c3c face=arial>身为一个COM+ 应用程式一部份的元件称为已设定元件</span><span id=Layer26></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>身为一个COM+ 应用程式一部份的元件称为已设定元件</span><span id=Layer27></font></p><hr><p><font size=2 color=#3c3c3c face=arial>关於这两种元件的资讯是储存在它们所存在的机器上之系统登录中。对於已设定元件来说,额外的资讯将会储存到一个系统登录之外的资料库,称RegDB。关於系统登录中已设定元件与未设定元件的资讯,以及储存在RegDB中未设定元件的资讯则合称为COM+目录(COM+ Catalog)。在这个目录中的资讯可透过元件服务管理工具存取,它是一个MMC嵌入单元。或者也可以直接透过标准的COMAdminCatalog 实作之ICOMAdminCatalog介面存取。当一个客户端从一个已设定元件建立一个物件时,COM runtime便检查目录,得知关於物件的资讯,然後判断它需要哪些服务。运作的情况稍後再详述。</span><span id=Layer28></font></p><font color=#3e72d7 face=arial size=4><b>COM+中物件建立的过程</span><span id=Layer29></b></font><p><font size=2 color=#3c3c3c face=arial>对於在桌上型电脑上执行,并存取某些伺服器上已设定元件的客户端机器来说,COM runtime不留痕迹地提供它的服务,客户端不需为此进行某些特殊的动作。取代的作法,客户端仍照往常的方式建立一个COM物件,呼叫它的method,然後在不需要的时侯释放这个物件。COM runtime默默地提供物件所要求的服务。</span><span id=Layer30></font></p><p><font size=2 color=#3c3c3c face=arial>客户端仍不会察觉COM runtime 提供给物件的服务</span><span id=Layer31></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>客户端仍不会察觉COM runtime 提供给物件的服务</span><span id=Layer32></font></p><hr><p><font size=2 color=#3c3c3c face=arial>不过COM runtime如何得知这些服务为何呢?答案是每个已设定元件都有一组特定的属性,大部份储存在RegDB。这些属性能够设定的值将在本章中讨论;现在要了解的重点是当物件建立时,COM runtime立即检视这些属性,然後依照这些属性为新物件建立适当的context。基於这个context的资讯,COM runtime便能判断物件需要的服务为何了。</span><span id=Layer33></font></p><p><font size=2 color=#3c3c3c face=arial>一个已设定元件的属性会影响从那个元件建立的物件之context</span><span id=Layer34></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个已设定元件的属性会影响从那个元件建立的物件之context</span><span id=Layer35></font></p><hr><p><font size=2 color=#3c3c3c face=arial>图8-3阐述一个简单的建立过程。在这个范例中,一个桌上型的客户端要求以标准的方式建立物件(就是所谓的启动),使用CoCreateInstance,或客户端的程式语言所用的任一个适当的呼叫动作。(这个范例假设一个DCOM客户端,若为一个Web客户端,则建立物件的呼叫必需由一个执行在Windows 2000伺服器机器上的ASP网页发行出来,以回应使用者经由HTTP 从浏览器发出来的要求。)虽然图中并未显示,客户端的要求会导致客户端机器上的COM runtime检查之前</span><span id=Layer36> <a target='_new' href=205.htm#>第五章</span><span id=Layer37></a> 所描述的系统登录,然後传送建立物件的要求到伺服器机器。</span><span id=Layer38></font></p><p><font size=2 color=#3c3c3c face=arial>客户端可以如往常一样呼叫CoCreateIns-tance 从已设定元件建立物件</span><span id=Layer39></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>客户端可以如往常一样呼叫CoCreateIns-tance 从已设定元件建立物件</span><span id=Layer40></font></p><hr><p><font size=2 color=#3c3c3c face=arial>接下来,伺服器机器上的COM runtime便会检查机器中COM+目录的CLSID_X。在此便可以找到关於这个CLSID所指的类别的许多丰富资讯。最基本的资讯是,它可以得知这个CLSID参考到一个已设定元件或是一个未设定元件。如</span><span id=Layer41> <a target='_new' href=205.htm#>第五章</span><span id=Layer42></a> 中所描述,若CLSID_X参考到一个未设定元件,则所有关於这个类别的资讯便储存在系统登录中。然而,假设CLSID_X参考到一个已设定元件,COM runtime便如同找寻未设定类别一样,从系统登录(Registry)找寻基本的资讯,其中包含这个类别的档案是哪一个。不过COM runtime同样会从RegDB搜寻已设定元件的许多相关资讯,包含了元件归属於哪一个COM+应用程式,以及曾设定了元件的各种属性之属性值...。有了所有的资讯,现在COM runtime就可以建立物件,确保它们在正确的行程中启动。COM runtime同样也会为物件在记忆体中建立适当的context,其中包含目录中这个类别的所有设定值。</span><span id=Layer43></font></p><p><font size=2 color=#3c3c3c face=arial>物件的context会受COM+目录中物件类别的资讯所影响</span><span id=Layer44></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件的context会受COM+目录中物件类别的资讯所影响</span><span id=Layer45></font></p><hr><br><center><a target=_new href=imagesh/8-3.gif><img border=0 src='imagesl/8-3.gif'></a></center></span><span id=Layer46><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-3</span><span id=Layer47> </b></font>在启动的过程中,COM runtime检视物件设定的属性,然後为物件建立适当的context。</span><span id=Layer48></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>到目前为止,我们已知假设受COM runtime所管理的物件之建立者是一个没有Context的客户端。不过,再假设一旦这个简单的客户端已建立一个如先前描述的新COM物件,这个物件本身希望建立其它的物件。那麽现在会发生什麽事?</span><span id=Layer49></font></p><p><font size=2 color=#3c3c3c face=arial>运作的过程看起来很类似。然而,如图8-4所展示,有些很重大的不同点。一如往常,执行的物件X可以发行一个CoCreateInstance,或使用的语言支援呼叫,然後COM runtime将会执行必要的步骤来建立这个物件。如图所示,runtime在COM+目录中查阅CLSID_Y,然後找寻这个类别的必要资讯,再用这些资讯正确地建立物件。</span><span id=Layer50></font></p><p><font size=2 color=#3c3c3c face=arial>在这个情况下,物件的建立者已经拥有一个context,而其包含的资讯必在建立的过程中列入考虑。若新物件的属性与物件建立者的属性相容,新物件将不会建立新的context。取代的作法是,它将会与建立者共享context。若两个物件的需求中有任何的不同点(这是目前最常见的案例),COM runtime将会为新的物件建立新的context。当然,放置在新context的值将会继承自目录中所找到的资讯,以及物件建立者Context中的值。视许多外在因素影响,某些建立者的属性能够下传到新的物件。关於这些属性将会在本章稍後再阐述,不过目前已足够能了解一个物件建立另一个物件的时机为何,新物件的context包含从COM+目录,以及物件建立者的Context两者继承而来的。</span><span id=Layer51></font></p><p><font size=2 color=#3c3c3c face=arial>一个物件的context可能包含了从它的建立者继承而来的资讯</span><span id=Layer52></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个物件的context可能包含了从它的建立者继承而来的资讯</span><span id=Layer53></font></p><hr><p><font size=2 color=#3c3c3c face=arial>Context最後一个值得注意的是跨context的呼叫 (在同一个apartment中,且不同context的COM物件之间相互叫用method) 承担了一些负载。当stub与proxy用在不同的机器、不同的行程,或不同apartment之间的呼叫时,这两者并非必要的。共享apartment,但不共享context的物件之间相互叫用时,便利用了类似上述的软体,称轻量级的proxy。COM runtime自动地建立并使用这些proxy,因此一个程式设计师从来就不会看到它们。它们的存在仍旧代表着跨不同的context共享一个介面指标需要程式设计师的特别关照。</span><span id=Layer54></font></p><p><font size=2 color=#3c3c3c face=arial>在不同的context中呼叫一个物件将会使用轻量级的proxy</span><span id=Layer55></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>在不同的context中呼叫一个物件将会使用轻量级的proxy</span><span id=Layer56></font></p><hr><p><font size=2 color=#3c3c3c face=arial>补捉拥有不同context的物件之间的呼叫就是所谓的拦截(interception)。Microsoft已经告诉某些人放宽拦截的机制,允许协力厂商的软体能插入呼叫路径中。不过在COM+ 1.0中这是不可能的。</span><span id=Layer57></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>补捉拥有不同context的物件之间的呼叫就是所谓的拦截(interception)。Microsoft已经告诉某些人放宽拦截的机制,允许协力厂商的软体能插入呼叫路径中。不过在COM+ 1.0中这是不可能的。</span><span id=Layer58></font></p><hr><br><center><a target=_new href=imagesh/8-4.gif><img border=0 src='imagesl/8-4.gif'></a></center></span><span id=Layer59><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-4</span><span id=Layer60> </b></font>当一个物件建立另一个物件时,新物件可以继承物件建立者的context或与物件建立者共享。</span><span id=Layer61></td></table></font></center><font color=#3e72d7 face=arial size=4><b>存取Context资讯</span><span id=Layer62></b></font><p><font size=2 color=#3c3c3c face=arial>事实上受COM runtime管理的每一个物件都需要与它的context以及runtime本身的context进行互动。为了达到这个目的,COM runtime显露许多不同的介面,每个介面包含的method允许一个执行中的物件能和它的Context资讯一起运作。在这之中的是IObjectContext,这个介面最早是由已经走向历史的MTS Executive提供的。COM+整修IObjectContext所提供的函数,增加了其它的介面,提供相同的method,不过以不同的方式进行分组,然後再加上一些新特性。这些新介面包含了IObjectContextInfo、ISecurityCallContext、与IContextState,稍後在本章中介绍。有些人争论着既然新介面已大量取代了IObjectContext所提供的服务,新的应用程式应该使用新介面而不要使用旧介面。不过IObjectContext仍旧是存取COM+核心服务最简单的方式,因此在大部份的讨论中,我将假设使用这个传统的介面。</span><span id=Layer63></font></p><p><font size=2 color=#3c3c3c face=arial>物件存取他们的context要透过IObject-Context 与其它介面</span><span id=Layer64></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件存取他们的context要透过IObject-Context 与其它介面</span><span id=Layer65></font></p><hr><p><font size=2 color=#3c3c3c face=arial>其中一个例外情形是IObjectContext's CreateInstance method。这个method对MTS来说是相当重要的,它是MTS物件用来建立另一个物件的唯一方式。今日,虽然它仍旧可以运作,不过IObjectContext::CreateInstance是相当庞大的旧式方案。目前,COM物件可以用标准的CoCreateInstance呼叫来建立其它的COM物件。</span><span id=Layer66></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>其中一个例外情形是IObjectContext's CreateInstance method。这个method对MTS来说是相当重要的,它是MTS物件用来建立另一个物件的唯一方式。今日,虽然它仍旧可以运作,不过IObjectContext::CreateInstance是相当庞大的旧式方案。目前,COM物件可以用标准的CoCreateInstance呼叫来建立其它的COM物件。</span><span id=Layer67></font></p><hr><p><font size=2 color=#3c3c3c face=arial>若要呼叫IObjectContext中的method,物件必需要先取得这个介面的指标。IObjectContext是实作在ObjectContext物件中(有时称为context物件)。如图8-5所示,若要取得IObjectContext的介面指标,COM物件可以呼叫GetObjectContext (在Visual Basic中) 或CoGetObjectContext (在C++中),它们是COM runtime所提供的API函数。一旦拥有这个指标,物件就可以呼叫IObjectContext的method,以便使用COM runtime所提供的许多服务。其中一个重要的服务便是自动交易处理,也就是下一个主题。</span><span id=Layer68></font></p><p><font size=2 color=#3c3c3c face=arial>物件呼叫CoGetObject-Context以取得IObjectCon-text的指标</span><span id=Layer69></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件呼叫CoGetObject-Context以取得IObjectCon-text的指标</span>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -