<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    OSGi Declarative Services簡介

    在 OSGi 服務平臺上構建應用時,必須考慮各種服務之間依賴關系及服務的管理,應用所依賴的服務有可能在任何時候被注銷或者更新,用戶在完成對 Service 的發布、查找、綁定的同時,還需要對服務的狀態進行監聽,以便作出適當的響應,所以在 OSGi 服務平臺上,對服務依賴關系的動態管理至關重要。在 OSGi Release 4 中,提出了 Declarative Services 規范,通過該規范可以方便地對服務之間的依賴關系和狀態進行監聽和管理。在本文中,將對 Declarative Services 規范進行介紹并且基于該規范開發一個實例。

    Declarative Services簡介

    Declarative Services 是一個面向服務的組件模型,它制訂的目的是更方便地在 OSGi 服務平臺上發布、查找、綁定服務,對服務進行動態管理,如監控服務狀態以及解決服務之間的復雜的依賴關系等問題。Declarative Services 采用服務組件的延遲加載以及組件生命周期管理的方式來控制對于內存的占用以及啟動的快速,很好的解決了傳統的 OSGi 服務模型在開發和部署比較復雜應用時內存占用大、啟動慢等問題,并且對服務組件的描述采用XML來實現,十分便于用戶理解和使用。在 Declarative Services 中,Component 可以是 Service 的提供者和引用者,一個 Component 可以提供 0 至多個 Service,也可以引用 0 至多個 Service,并且采用component 方式封裝 Service,方便了對 Service 的復用,從開發者的角度來看,該服務組件模型簡化了在 OSGi 服務平臺中的編程模型。Declarative Services 規范參考了"Automating Service Dependency Management in a Service-Oriented Component Model"一文的有關概念,讀者可從參考資料獲得該文的詳細信息。


    Component Satisfied 概念介紹

    在 Declarative Services 中,一個服務組件是包含在 Bundle 應用中的普通的 Java 類,每個Component 可以暴露出多個服務,同時也可依賴于多個服務,通過XML文件描述和服務組件相關的信息,SCR(Service Component Runtime)根據服務組件配置文件控制著組件配置的激活(Activate)和鈍化(Deactivate),服務組件配置文件包括如組件的類型、組 件的實現以及引用的服務等信息。在詳細介紹服務組件(Component)之前,我們必須了解 Component Satisfied 的概念,在 Declarative Services 中,Component Satisfied 與 Component 的生命周期密切相關。如 Component 激活的前提條件之一就是 Component Satisfied,而在 Component 的運行過程中,出現 Unsatisfied 時,Component 將被鈍化。主要由以下兩點決定 Component 是否處于Satisfied 狀態:

    Component 為 Enabled 狀態,Component 的生命周期包含在引用它的 Bundle 應用的生命周期之內,只有在 Bundle 處于 Active 狀態時,Component 才有可能為 Enabled 狀態,在 Bundle處于 Stop 狀態時,Bundle 中所有的 Component 都處在 Disabled 狀態。Component 初始的Enabled 狀態可以在服務組件配置文件中設定。

    Component 的配置是可以被引用和解析的,Component 中引用的 Service 也是 Satisfied 的,引用的 Service 至少有一個是處于可用狀態的,或者引用的 Service 在服務組件配置文件里配置了可為 0 個可用狀態的 Service。

    當上述兩個條件中任何一個不滿足時,組件配置將變為 Unsatisfied 狀態,組件配置將被鈍化。在理解 Component Satisfied 的概念后,下面講解三種類型的服務組件。


    Component 介紹

    在 Bundle 啟動時, Declarative Services 裝載相應的服務組件配置文件,配置文件在MAINFEST.MF 文件的 Service-Component 屬性指定,解析配置文件,獲取服務組件引用的 Service ,如果判斷組件 Satisfied 狀態的兩個條件滿足時, Declarative Services 就認為這個組件是 Satisfied 的。

    Immediate Component

    對于 Immediate Component,如果組件配置處于 Satisfied 狀態,將會立即被激活,并且如果該配置指定了服務,那么 SCR 會注冊該服務并且立即激活該服務組件。在 SCR 激活組件配置時,實現服務組件類的 activate 方法將會被調用,在SCR鈍化組件配置時,deactivate方法將會被調用。Immediate Component的狀態圖如圖1所示:


    圖示1:Immediate Component狀態圖
    圖示1:Immediate Component狀態圖

    Delayed Component

    對于 Delayed Component ,如果組件配置處于Satisfied狀態,該組件并不會立即被激活,Declarative Services 會根據組件配置文件中的 Service 的配置,注冊相應的Service 的信息,直到該服務組件被請求時, Declarative Services 才會激活該組件配置 。 Delayed Component 延遲了 Component 類的創建,當該服務組件的服務收到請求時,該 Component 類的 activate 方法才會被調用。如果一個 Component 不是 Factory Component,并且在其組件配置文件中指定了服務,組件的 immediate 屬性設置為 false,那么該組件就是 Delayed Component。Delayed Component 的狀態圖如圖 2 所示:


    圖示2:Delayed Component 狀態圖
    圖示2:Delayed Component 狀態圖

    Factory Component

    通過在組件配置文件中設置 Component 的 factory 屬性,將 Component 聲明為 Factory Component。該組件在激活后注冊的是一個 Component Factory 服務,只有在調用 Component Factory 的 newInstance 方法后才會激活相應的各個組件,每一次調用 newInstance 方法,都會創建和激活一個新的組件配置。如果在組件配置文件中聲明了服務,那么在該組件激活之前,聲明的服務被注冊。Factory Component 的狀態圖如圖3所示:


    圖示3:Factory Component狀態圖
    圖示3:Factory Component狀態圖

    在三種類型的服務組件中,Delayed Component 很好的解決了系統服務的動態性問題,同時也節省了內存的占用。 服務組件的生命周期受 Bundle 生命周期影響,當 Bundle 停止時,那么Bundle 中所有的服務組件也就停止。


    Service 的發布、查找、綁定

    在 OSGi 服務平臺中,大部分 Bundle 應用都是基于服務的,服務的發布、引用十分重要,下面講一下利用服務組件如何進行 Service 的發布、查找和綁定。

    Service 的發布

    對于 Component 中 Service 的發布,需要在組件配置文件中定義 service 元素,該 service元素至少包括一個或多個 provide 元素,該 provide 元素定義了該 component 提供的服務接口,它只有一個屬性 interface,該 interface 定義了提供服務的接口,并且允許是實現該服務接口的類名。可以看出,利用 Declarative Services 發布 Service 非常簡單,只要 Component 實現了定義的 Service 的接口即可。如在本文所講解例子中,在組件配置文件中,聲明姓名查詢服務如圖 4 所示:


    圖示4:姓名查詢服務聲明
    圖示4:姓名查詢服務聲明

    Service 的查找和綁定

    在 Declarative Services 中,Component 所引用的服務,稱為 Target Service,當 Component 中引用的 Target Service 也是 Satisfied 時,即引用的 Service 至少有一個是處于可用狀態的,或者引用的 Service 在服務組件配置文件里配置了可為 0 個可用狀態的 Service,組件配置才有可能被激活。在組件實現類中,有兩種策略可以獲得在組件配置文件里指定的 Target Service,是事件策略和 Lookup 策略。

    事件策略

    在服務組件激活的過程中,SCR 必須將組件配置文件里指定的 Target Service 綁定到組件配置中。在事件策略中,SCR 通過調用組件實現類的一個方法將 Target Service 綁定到組件中,同樣,SCR 通過調用另外一個方法來取消綁定,這些方法在組件配置文件中 reference 元素的bind 和 unbind 屬性指定。事件策略主要適用于服務組件所引用的 Target Service 處在動態變化中。如在本文例子中,如果采用事件策略引用姓名查詢服務,在配置文件中聲明和 Component 實現類中引用服務分別如圖示 5、圖示 6 所示:


    圖示5:采用事件策略的組件配置文件
    圖示5:采用事件策略的組件配置文件

    圖示 6:采用事件策略的綁定姓名查詢服務
    圖示 6:采用事件策略的綁定姓名查詢服務

    Lookup 策略

    在組件實現類中,通過調用 ComponentContext 的 locateService 方法來定位所引用的 Target Service ,該方法的參數是在組件配置文件里指定的 reference 元素的 name 屬性。如在本文例子中,如果采用 Lookup 策略引用姓名查詢服務,在配置文件中聲明和 Component實現類中引用服務分別如圖示 7、圖示 8 所示:


    圖示7:采用 Lookup 策略的組件配置文件
    圖示7:采用 Lookup 策略的組件配置文件

    圖示 8:采用 Lookup 策略的引用姓名查詢服務
    圖示 8:采用 Lookup 策略的引用姓名查詢服務

    在 OSGi 服務平臺中,即便 Component 已經綁定所引用的 Target Service,但是由于服務的動態性,它可能在任何時刻被注冊、替換或者注銷,這些變化可能使服務組件所引用的 Target Service 變成過時的引用,所以,在 Declarative Services 中,當這些情況發生時,Component必須采取某種策略去處理這些變化。Declarative Services 提供兩種策略,一種是 static 策略 ,另外一種是 dynamic 策略 ,默認情況下 Component 采用的是 static 策略。當采用static 策略時,如果引用的 Target Service 發生了變化,那么組件配置會被重新裝載并激活。當采用 dynamic 策略時,SCR 在不鈍化組件配置的情況下可以改變綁定的 Target Service。此外,Declarative Services 還提供很多功能,如可通過在 Component 的 reference 元素中增加 target 屬性來實現對所引用 Service 進行過濾;如可增加 cardinality 屬性來對引用 Service 的數量進行控制。關于 Declarative Services 更詳細的信息,請讀者參見本文的參考資料。


    使用 Eclipse 開發服務組件

    在本文中,我們結合 Equinox 項目關于 Declarative Services 的實現,開發兩個使用服務組件的 Bundle 應用,其中第一個 Bundle 的服務組件的配置文件中聲明注冊了一個姓名查詢服務,用于判斷所給姓名是否在已定義的查詢列表中;第二個 Bundle 應用的服務組件的配置文件中靜態引用了第一個 Bundle 應用服務組件所注冊的姓名查詢服務,如果用戶所給的姓名包含在查詢列表中,將返回正確的信息。最后,將開發的 Bundle 應用部署的 Equinox OSGi 框架中,用戶可以在 OSGi 控制命令行中輸入命令來查詢關于框架和 Bundle 應用的具體信息。讀者可以從參考資料中獲得本文 Bundle 應用的源代碼。關于 Equinox 項目的詳細信息,請查閱參考資料信息。

    (1)首先定義所提供服務的接口,然后 Bundle 應用的服務組件實現這個服務接口。在本例中,定義姓名查詢接口 NameService.java。下面是該接口的源代碼:


    NameService Interface 源代碼
    package ds.example.service;
    /**
    * A simple service interface that defines a name service.
    * A name service simply verifies the existence of a Name.
    **/
    public interface NameService {
    /**
    * Check for the existence of a Name.
    * @param name the Name to be checked.
    * @return true if the Name is in the list,
    * false otherwise.
    **/
    public boolean checkName(String name);
    }

    該服務接口很簡單,只包含一個需要實現的方法。通常為了將服務接口和服務實現相分離,要將該服務接口單獨放在一個包內。

    (2 ) 定義 Bundle 描述文件 MANIFEST.MF,Bundle 應用 dsExample 的 MANIFEST.MF 文件如下:


    MANIFEST.MF 文件信息
    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: DsExample Service
    Bundle-SymbolicName: dsExample
    Bundle-Version: 1.0.0
    Bundle-Localization: plugin
    Import-Package: org.osgi.framework;version="1.3.0",
    org.osgi.service.component;version="1.0.0"
    Service-Component: OSGI-INF/component.xml
    Export-Package: ds.example.service

    其中,Service-Component 屬性指定了該 Bundle 應用的服務組件配置文件,在該配置文件中聲明服務并且指定了實現該服務的組件;Export-Package 屬性指定了該 Bundle 輸出的共享包,該屬性可以使其他的 Bundle 應用引用所定義的服務接口。

    (3)編輯該 Bundle 應用的服務組件配置文件,正如前面所講 Service 的發布那樣,該服務組件的配置文件如下:


    dsExample Bundle 的組件配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <component name="dsExample">
    <implementation
    class="example.osgi.NameImpl"/>
    <service>
    <provide interface="ds.example.service.NameService"/>
    </service>
    </component>

    其中,Service 元素定義了所提供服務的接口;Implementation 元素定義了實現該服務接口的組件類名。

    (4)實現在服務組件配置文件中指定的服務組件,源代碼如下所示: dsExample 實現組件源代碼


    public class
    NameImpl
    implements NameService {
    // The set of names contained in the arrays.
    String[] m_name =
    { "Marry", "John", "David", "Rachel", "Ross" };

    protected void activate(ComponentContext context) {
    System.out.println("NameService Component Active,within the bundle
    lifecircle.");
    }
    public void
    deactivate(ComponentContext context)
    throws Exception {
    System.out.println("NameService Component Deactive,within the bundle
    lifecircle.");
    }
    public boolean checkName(String name) {
    // This is very inefficient
    for
    (
    int i = 0; i < m_name.length; i++)
    {
    if (m_name[i].equals(name))
    {
    return true;
    }
    }
    return false;
    }
    }

    該服務組件實現了 NameService 接口,并且在服務組件激活和鈍化時分別打印出相應信息,以便在運行 Bundle 應用時,能夠跟蹤 Component 的生命周期。

    (5)創建項目名為 dsExampleClient 的 Bundle 應用,該應用的服務組件在 OSGi 平臺上查詢并引用 dsExample Bundle 應用已經注冊的姓名查詢服務,然后從標準輸入讀入用戶所輸入的姓名信息,判斷所輸入姓名是否有效。關于 dsExampleClient 應用,讀者可從參考資料中獲得完整源代碼,下面只給出該 Bundle 應用的服務組件配置文件:


    dsExampleClient Bundle 的組件配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <component name="dsExampleClient">
    <implementation
    class="exampleclient.osgi.CheckNameClient"/>
    <reference name="nameservice"
    interface="ds.example.service.NameService"
    cardinality="1..1"
    policy="static"
    />
    </component>

    其中,reference 元素定義了該組件所引用的服務接口,并且指明該組件采用 static 策略;Implementation 元素指定了實現組件的類。


    Bundle的部署及運行

    在 Eclipse 平臺中,在菜單中選擇 Run-->Run AS-->Equinox FrameWork 來啟動 OSGi 服務平臺。注意在Equinox啟動配置控制臺中的Target Platform 中選擇org.eclipse.equinox.ds選項,該plug-in是Equinox關于Declarative Services的實現,將兩個Bundle應用設置為取消自動啟動選項。當OSGi Equinox FrameWork啟動后,在OSGi控制命令臺中輸入ss命令,可以查看OSGi服務平臺中已經安裝的Bundle應用信息及其狀態。如圖9所示,可以 看到dsExample和dsExampleClient Bundle應用處于Resolved狀態。


    圖示9:Bundle狀態查詢
    圖示9:Bundle狀態查詢

    在OSGi控制命令臺中利用start命令啟動 dsExample 應用,用ss命令查看啟動后的Bundle應用信息及其狀態,可以看出 dsExample Bundle 處于Active狀態,但是該Bundle的服務組件并沒有被激活,如果被激活,將會在OSGi控制命令臺中打印出"NameService Component Active,within the bundle lifecircle."字樣,說明該服務組件為 Delayed Component 類型,該組件并不會立即被激活,直到該服務組件被請求時, Declarative Services 才會激活該組件配置,Delayed Component延遲了組件的加載,節省了內存的占用 ,如圖10所示:


    圖示10:啟動dsExample Bundle
    圖示10:啟動dsExample Bundle

    在OSGi控制命令臺中利用start命令啟動dsExampleClient應用,可以看出兩個 Bundle的服務組件相繼被激活,如圖11所示:


    圖示11:啟動dsExampleClient Bundle
    圖示11:啟動dsExampleClient Bundle

    在OSGi控制命令臺中利用stop命令停止dsExample應用,可以看出兩個 Bundle的服務組件相繼被鈍化,如圖12所示:


    圖示12:停止dsExample Bundle
    圖示12:停止dsExample Bundle

    需要注意的是服務組件的生命周期受 Bundle 生命周期的影響,當 Bundle 停止時,那么Bundle 中所有的服務組件也就停止。


    總結

    Declarative Services 是一個面向服務的組件模型,其目的是更方便地在 OSGi 服務平臺上發布、查找、綁定服務,對服務進行動態管理。Declarative Services 采用服務組件的延遲加載以及組件生命周期管理的方式來控制對于內存的占用以及啟動的快速,對 Service 的動態管理,使得系統可以根據系統運行的情況做出及時的響應,增強了系統的穩定性和靈活性。項目Gravity 也采用了類似的機制,有興趣的讀者可以參見參考資料中的詳細信息。

    posted on 2008-05-08 10:45 gembin 閱讀(1172) 評論(0)  編輯  收藏 所屬分類: OSGi

    導航

    統計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: 久久亚洲精品成人综合| 无码视频免费一区二三区 | 亚洲免费一区二区| 四虎影库久免费视频| 免费看香港一级毛片| 无码一区二区三区免费视频| 国产精品久久久久免费a∨ | 久久久久久国产a免费观看不卡| 人妻仑刮八A级毛片免费看| 羞羞的视频在线免费观看| 免费一级毛片在线播放视频免费观看永久 | 国产AV无码专区亚洲A∨毛片| 国产aⅴ无码专区亚洲av| 亚洲av午夜成人片精品网站 | 亚洲人妻av伦理| 亚洲无线码在线一区观看| 亚洲综合伊人久久大杳蕉| 国产亚洲美女精品久久久久狼| 亚洲成AV人片一区二区| 伊人久久综在合线亚洲2019| 亚洲午夜国产精品无卡| 亚洲色大成网站www永久网站| 久久亚洲精品无码网站| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 麻豆国产VA免费精品高清在线| 国产真人无遮挡作爱免费视频| 亚洲AV无码成人精品区大在线 | 免费v片在线观看视频网站| 韩国免费一级成人毛片| 国产精品免费视频一区| 精品国产亚洲一区二区在线观看| 国产亚洲综合网曝门系列| 亚洲精品中文字幕无码AV| 亚洲精品无码国产片| 人体大胆做受免费视频| 久久精品视频免费| 野花高清在线电影观看免费视频 | 日本高清高色视频免费| 嫖丰满老熟妇AAAA片免费看| 国产精品国产午夜免费福利看 | 亚洲精品天堂成人片?V在线播放 |