熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

利用 OSGi 解決 Eclipse 插件難題

2013-11-23 20:37:47  來源: Java開源技術 
本文介紹了一個采用 XML 的插件示例以便為定義好的擴展點注冊擴展通過使插件能夠感知 Extention Registry 並提供 OSGi 服務我們可以完成這一完整的組件退耦操作
  
  插件擴展點OSGi
  
  如您所知Eclipse 的組件架構是基於插件 的 這意味著將一組代碼組件化為單一的組件然後利用 Eclipse 框架注冊為其組件之一其他組件可以綁定該組件或調用該組件擴展點 是插件允許其他插件向公開擴展點的插件提供附加功能的方法現在利用所有這些插件並將其包裝到受控的運行時插件可在其中動態進出並且您可以獲得 OSGi(基本上來說)
  
  示例插件
  
  讓我們從公開擴展點的基本插件開始這樣可以為同義詞服務注冊新的字符串映射此項服務允許其他服務注冊一個詞並將其映射到另一個詞(同義詞)基本擴展包含非常簡單的元素一個詞當然還有一個新的同義詞此插件擴展點的基本結構如表 所示
  
  表 示例插件的元素
  

  


  我們還要將插件注冊為 OSGi 服務這意味著它只在顯式執行此操作時被加載並將可供其他客戶聲明性地使用為了使用該服務其他客戶只需了解 Interface 和 OSGi 類名稱在我們的示例中我們不會真正調用該服務因為擴展點是假設的我們將使用 OSGi API 以告知我們此項服務出入的時間所以我們可以正確地注冊擴展點
  
  現在這只是一個示例並且使用針對此概念的擴展點可能不是最好的方法我們用此基本示例要達到的目的是如何動態注冊新的擴展同時說明使用 OSGi API 的插件生命周期事件
  
  Mediator 插件
  
  下一個插件是第三方插件該插件了解已知的服務和擴展點但不想綁定到此插件因為後面它將依靠該插件進行運行時解析這意味著該插件可以駐留在所引用的插件 (panySynonymRegistry) 可能不存在的機器上因為我們現在生活在 OSGi 和動態運行時世界所以我們想確保插件在不引起運行時故障或錯誤的情況下運行我們的 mediator 插件將接受同義詞的 XML 文件並且通過使用提供的擴展點用 SynonymRegistry 插件注冊每個同義詞
  
  清單 用於概念驗證的示例 XML 文件
  
  Synonymsxml
  
  <?xml version= encoding=UTF?>
  
  <synonyms>
  
  <entry word=mediator synonym=broker/>
  
  <entry word=mediator synonym=gobetween/>
  
  <entry word=mediator synonym=interceder/>
  
  <entry word=mediator synonym=intermediary/>
  
  <synonyms>
  
  Mediator 插件在其 start() 方法中做的第一件事是用 OSGi 服務注冊為一個服務初始化偵聽器我們要在傳入 start() 方法的 BundleContext 對象上調用 OSGi 服務方法 addServiceListener()以下代碼展示了一個通過傳入代碼和我們感興趣的服務 ID 調用此 API 的示例
  
  contextaddServiceListener( this panySynonymRegistry
  
  通過提供過濾器可以告知 OSGi 服務注冊中心只需通知您指定服務中的狀態更改在本例中過濾器只是 SynonymRegistry 類的類名稱
  
  您可能會尋根究底答案就在啟動序列中在 OSGi 領域我們不是總知道另一服務可用的時間因此我們需要對此進行說明通過注冊為服務偵聽器我們可得知服務開始和停止的時間如果服務不可用則允許我們緩存同義詞當服務確實可用時我們會得到通知並注冊擴展
  
  注冊新擴展
  
  下面我們將講述本文的核心內容現在我們有了想為其提供動態擴展的數據 (Synonymsxml) 和已知的擴展點 (panySynonymRegistry Synonym)由於我們不知道何時初始化插件也不知道是否初始化 Synonym 插件所以我們只要在加載插件時嘗試注冊 XML 文件中的條目即可請記住這是一個展示概念的示例不應在生產代碼中這樣實施通常我們盡可能多地以惰性方式(延遲或在需要時)執行初始化
  
  Eclipse V 中的新特性是能夠在運行時提供擴展例如客戶可以編寫一個包含某個視圖的應用程序該視圖可以在單擊按鈕時創建一個透視圖透視圖被添加到擴展注冊表然後在可用透視圖的列表中顯示此功能的重要好處之一是它可以減輕插件之間的依賴性插件 A 可供在插件 B 中定義的平台使用無需依賴插件 B而且通過將此功能與 OSGi 框架結合插件可以檢查服務的存在性如果存在可從服務中定義的擴展點創建擴展這在使用面向服務架構的原則同時促進了真正動態的環境
  
  Eclipse V 中新公開的是 addContribution() 方法該方法在 IExtensionRegistry 接口中定義清單 中的代碼展示了可以通過 addContribution() API 添加擴展的方法addContribution() 方法旨在采用普通 XML 作為第一個參數中的 InputStream
  
  清單 通過 addContribution() API 添加擴展的方法
  
  IExtensionRegistry registry = RegistryFactorygetRegistry( )
  
  Object key = ((ExtensionRegistry) registry)getTemporaryUserToken( )
  
  ByteArrayInputStream is =
  
  new ByteArrayInputStream( buffertoString()getBytes() )
  
  try {
  
  registryaddContribution(is bundle null null key)
  
  }
  
  finally {
  
  try {
  
  isclose( )
  
  }catch (IOException e) {
  
  }
  
  }
  
  編寫本文的時候 意味著這是一個更改 Eclipse 未來版本的好機會 允許公眾訪問注冊表的用戶標記可以使用此內部 Eclipse 調用獲得下面的代碼展示了內部 API (getTemporaryUserToken()) 的使用
  
  Object key = ((ExtensionRegistry)registry)getTemporaryUserToken()
  
  但是在裡程碑式的下一版本 Eclipse V 版本中此標記不能公開訪問為了支持應用程序中的動態擴展啟動程序必須提供以下針對虛擬機的設置
  
  Declipseregistrynulltoken=true
  
  此定義現在允許我們將 null 用作 addContribution() API 中的 User Token現在我們的代碼看上去類似如下有關此問題中的 Bugzilla 對話請參見 Bugzilla bug 清單


  
  清單 getTemporaryUserToken()
  
  …
  
  try {
  
  registryaddContribution(is bundle null null null)
  
  }
  
  …
  
  上面顯示的緩沖區變量表示實際的 XML 塊此 XML 是我們可以在 pluginxml 文件內看到的精確副本回到我們的 SynonymRegistry 示例此擴展的 XML 將類似清單
  
  清單 SynonymRegistry 的 XML
  
  <plugin>
  
  <extension point=panysynonymregistry id=myExtension>
  
  <synonyms
  
  word=mediator
  
  synonym=broker/>
  
  </extension>
  
  </plugin>
  
  客戶可以考慮創建一個接受以下參數的包裝工廠類如擴展點 ID擴展 ID元素名稱(本例中是同義詞)實際屬性和資源包 ID該包裝類將參數格式化為類似上面代碼的 XML 字符串然後將此 XML 字符串讀入將被傳入到 IExtensionRegistry 接口的 addContribution() 方法的 ByteArrayInputStream 中只有此方法的其他必需參數是用戶標記和資源包 ID值得注意的一點是資源包 ID 應是做出該貢獻的資源包的 ID不是在其中定義擴展點的資源包的 ID
  
  警告和提示
  
  在 M(於 日構建的 Eclipse)中引入的一個特性是對 addContributions() 的調用是異步調用這意味著該擴展不可立即使用因為 Eclipse 啟動了一項執行實際注冊的作業簡單地說您必須開始自己的作業並與之同步以獲得任何類型的同步行為
  
  為了使此項任務更容易下面給出了三條提示
  
  ?創建一項將其本身注冊為一個 RegistryChangeListener 的新作業
  
  ?該作業運行時確保您的作業代碼偵聽 RegistryListener 回調的 isRegistered 集合
  
  ?一旦所有注冊完成即退出您的作業
  
  當然現在我們必須將調用代碼與生成的作業結合起來以獲得同步調用這只有在代碼要求立即使用擴展時才得到保證希望您的代碼設計為惰性這樣初始化就變得不重要
  
  結束語
  
  動態擴展的使用可以通過編程方式創建通過使用 OSGi 框架偵聽服務何時可用(加載或卸載)動態擴展增強了退耦功能一起使用這些技術將允許聲明性的貢獻和組件之間 % 退耦


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28797.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.