溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么執(zhí)行OSGi模塊化

發(fā)布時間:2022-01-11 16:34:00 來源:億速云 閱讀:157 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關(guān)怎么執(zhí)行OSGi模塊化,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

OSGi模塊化 - 

Lars Vogel,Simon Scholz(c)2008,2017 vogella GmbH版本5.2,202.02.2017

目錄

  • OSGi簡介軟件模塊化


  • 1.2。OSGi規(guī)范和OSGi實現(xiàn)

    OSGi是一組規(guī)范,在其核心規(guī)范中定義了Java的組件和服務(wù)模型。OSGi的實際優(yōu)點是每個軟件組件可以通過一組導出的Java包來定義其API,并且每個組件可以指定其所需的依賴性。

    組件和服務(wù)可以被動態(tài)地安裝,激活,去激活,更新和卸載。

    OSGi規(guī)范有幾個實現(xiàn),例如Eclipse Equinox,Knopflerfish OSGi或Apache Felix。

    Eclipse Equinox是基本OSGi規(guī)范的參考實現(xiàn)。它也是Eclipse應(yīng)用程序所基于的運行時環(huán)境。

    1.4。命名約定:簡單的插件

    一個插件可以通過Eclipse中通過生成文件  ? 新建  ? 其他...  ? 插件開發(fā)  ? 插件工程菜單項。相應(yīng)的向?qū)г试S指定多個選項。此腳本調(diào)用使用以下選項生成的插件:簡單插件簡單包。

    • 無激活劑

    • 對用戶界面沒有貢獻

    • 不是一個富客戶端應(yīng)用程序

    • 生成時沒有模板

2.1。清單文件(MANIFEST.MF)

技術(shù)上OSGi插件是 帶有附加元信息的.jar文件。此元信息存儲在 META-INF / MANIFEST.MF 文件中。此文件稱為 清單 文件,是標準Java規(guī)范的一部分,OSGi向其中添加了額外的元數(shù)據(jù)。根據(jù)Java規(guī)范,任何Java運行時必須忽略未知的元數(shù)據(jù)。因此,在其他Java環(huán)境中可以無限制地使用插件。

以下列表是清單文件的示例。

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Popup Plug-in Bundle-SymbolicName: com.example.myosgi; singleton:=true Bundle-Version: 1.0.0 Bundle-Activator: com.example.myosgi.Activator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.6

下表說明了清單文件中的標識符。有關(guān)OSGi中通常使用的版本模式的信息,請參閱使用OSGi進行語義版本控制。

表1.清單文件中的OSGi標識符
標識符 描述

軟件包名稱

插件的簡短描述。

Bundle-SymbolicName

插件的唯一標識符。如果此插件使用Eclipse的擴展點功能,則必須將其標記為Singleton。您可以通過在Bundle-SymbolicName標識符之后添加以下語句來實現(xiàn): ; singleton:=true

Bundle-Version

定義插件版本,如果發(fā)布了插件的新版本,則必須遞增。


Bundle-Activator

定義實現(xiàn)接口的可選激活器類BundleActivator。該類的實例在插件被激活時創(chuàng)建。無論何時啟動或停止插件,都會調(diào)用它start()和stop()方法。OSGi激活器可用于在啟動期間配置插件。激活程序的執(zhí)行會增加應(yīng)用程序的啟動時間,因此應(yīng)謹慎使用此功能。

Bundle-RequiredExecutionEnvironment(BREE)

指定運行插件所需的Java版本。如果不滿足此要求,則OSGi運行時不會加載插件。

Bundle-ActivationPolicy

將此設(shè)置為 延遲 將告訴OSGi運行時,只有當其插件之一(即類和接口)被其他插件使用時,才會激活該插件。如果未設(shè)置,Equinox運行時不會激活插件,即,此插件提供的服務(wù)不可用。

Bundle-ClassPath

Bundle-ClassPath指定從bundle加載類的位置。默認值為“。”。它允許從bundle的根加載類。您還可以向其中添加JAR文件,這些文件稱為 嵌套JAR文件。

2.3。使用OSGi的語義版本化

OSGi建議對 通過 字段標識符定義的版本號使用 。。模式 Bundle-Version。如果更改插件代碼,請根據(jù)以下規(guī)則集增加版本。

  • 如果所有更改都向后兼容,則會增加。

  • 如果公共API已更改,但所有更改都向后兼容,則增加。

  • 如果更改不向后兼容,則會增加。

有關(guān)此版本方案的更多信息,請參閱 Eclipse版本編號Wiki。

2.5。插件的生命周期在OSGi

通過在OSGi運行時中安裝插件,插件將保留在本地bundle緩存中。OSGi運行時然后嘗試解析它的依賴關(guān)系。

如果解決了所有必需的依賴關(guān)系,則插件位于

RESOLVED 狀態(tài),否則它保持在 INSTALLED 狀態(tài)。

在存在可以滿足依賴性的幾個插件的情況下,使用具有最高有效版本的插件。

如果版本相同,則使用具有最低唯一標識符(ID)的插件。每個插件都會在安裝期間獲取框架分配的此ID。

插件啟動時,其狀態(tài)為 STARTING。成功啟動后,它將變?yōu)?nbsp;ACTIVE

此生命周期如下圖所示。

怎么執(zhí)行OSGi模塊化

3.插件的API定義

MANIFEST.MF文件中,插件還通過導出包標識符定義其API。未顯式導出的所有軟件包對其他插件不可見。

怎么執(zhí)行OSGi模塊化

所有這些限制都通過特定的OSGi實施classloader。每個插件都有自己的類加載器。不使用reflection.s不能訪問受限類

不幸的是,OSGi不能阻止你使用Java反射來訪問這些類。這是因為OSGi基于尚不支持模塊化層的Java運行時。

通過x-internal標志,OSGi運行時可以將導出的包標記為臨時。這允許其他插件使用相應(yīng)的類,但表示這些類不被視為官方API。

以下屏幕截圖顯示如何x-internal在清單編輯器中設(shè)置包。

怎么執(zhí)行OSGi模塊化

這是相應(yīng)的清單文件的外觀。

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Provider Bundle-SymbolicName: de.vogella.osgi.xinternal.provider Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: de.vogella.osgi.xinternal.provider;x-internal:=true

您可以配置Eclipse Java編輯器如何顯示臨時API的使用。這種訪問可以被配置為顯示為,錯誤,警告或者如果這種訪問應(yīng)當不導致附加消息。

默認值為顯示警告消息。您可以通過Eclipse的喜好調(diào)整這個窗口  ? 首選項  ? 的Java  ? 編譯器  ? 錯誤/警告首選項設(shè)置。

怎么執(zhí)行OSGi模塊化

您可以定義一組插件可以訪問臨時API,而不會出現(xiàn)警告或錯誤消息。這可以通過x-friends指令完成。如果您在清單編輯器的“ 運行時 ”選項卡上的“ 包可見性”部分添加插件,則會添加此標志。

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Provider Bundle-SymbolicName: de.vogella.osgi.xinternal.provider Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: de.vogella.osgi.xinternal.provider;x-friends:="another.bundle"

該x-friends設(shè)置具有相同的效果,x-internal但是x-friends設(shè)置中提到的所有插件都可以訪問包,而不會收到錯誤或警告消息。

4.1。OSGi控制臺

OSGi控制臺就像一個命令行shell。在此控制臺中,您可以鍵入命令以執(zhí)行OSGi操作。這可以用于分析應(yīng)用程序的OSGi層上的問題。

例如,使用命令 ss 獲取所有包的概述,它們的狀態(tài)和bundle-id。下表是最重要的OSGi命令的參考。

表2. OSGi命令
命令 描述

help

列出可用的命令。

ss

列出安裝的軟件包及其狀態(tài)。

ss vogella

列出捆綁包及其在其名稱中包含vogella的狀態(tài)。

start 

使用 ID 啟動包。

stop 

使用 ID 停止捆綁。

diag 

診斷特定包。它列出所有缺失的依賴項。

install URL

從URL安裝包。

uninstall

使用 ID 卸載捆綁軟件。

bundle 

顯示具有 ID的捆綁包的信息,包括已注冊和已使用的服務(wù)。

headers 

顯示包的MANIFST.MF信息。

services filter

顯示所有可用的服務(wù)及其消費者。過濾器是一個可選的LDAP過濾器,例如,查看提供ManagedService實現(xiàn)的所有服務(wù)使用“services(objectclass = * ManagedService)”命令。

4.3。Telnet

如果 在啟動配置中指定 -console參數(shù),Eclipse將允許您與OSGi控制臺交互。默認情況下,使用Eclipse IDE創(chuàng)建的OSGi啟動配置包含此參數(shù)。通過以下參數(shù),您可以打開一個端口,您可以通過telnet協(xié)議連接到該端口。

-console 5555

如果打開到OSGi控制臺的telnet會話,您可以使用tab完成和類似于 Linux下的Bash shell 的命令歷史記錄 。

5.下載Eclipse SDK

如果您計劃向Eclipse平臺添加功能,則應(yīng)下載最新的Eclipse版本。官方版本具有穩(wěn)定的API,因此是添加插件和功能的良好基礎(chǔ)。

Eclipse IDE提供了不同的版本。雖然可以在任何Eclipse包中安裝必要的工具,但通常更容易下載Eclipse Standard發(fā)行版,其中包含插件開發(fā)的所有必要工具。其他軟件包增加了Eclipse插件開發(fā)不需要的更多工具。

瀏覽到Eclipse下載站點并下載Eclipse Standard軟件包。

怎么執(zhí)行OSGi模塊化

Eclipse 4.5還提供了一個新的Eclipse安裝程序安裝程序。如果您要下載多種版本的Eclipse,安裝程序?qū)⒎浅S杏茫驗樗褂霉蚕戆惭b池用于常用插件。

6.1。為數(shù)據(jù)模型創(chuàng)建插件

創(chuàng)建一個名為com.example.e4.rcp.todo.model的簡單插件項目(請參閱命名約定:簡單插件)。

以下屏幕截圖描述了插件項目向?qū)У牡诙摷捌湎鄳?yīng)的設(shè)置。按此頁上的完成按鈕,以避免使用模板。

怎么執(zhí)行OSGi模塊化

<h4 id="create-the-base-class"  font-weight:300;color:#ba3925;text-rendering:optimizelegibility;line-height:1.2;font-size:1.6875em;word-spacing:-0.05em;"="">6.2。創(chuàng)建基類

創(chuàng)建com.example.e4.rcp.todo.model包和以下模型類。

package com.example.e4.rcp.todo.model;  import java.util.Date;  public class Todo {  private final long id; private String summary = ""; private String description = ""; private boolean done = false; private Date dueDate = new Date();  }
您的最終ID字段出現(xiàn)錯誤。此錯誤在下一節(jié)中解決。

6.4。生成getter和setter方法

使用來源  ? 生成getter和setter ...菜單來創(chuàng)建getter和setter方法為您的字段。

為什么id字段標記為final?

ID是終局的,因此Eclipse將創(chuàng)建只有一個getter。這是正確和希望的。我們將使用此字段來生成equals和hashCode()方法,因此它不應(yīng)該是可變的。更改這是在使用的字段equals和hashCode()方法可以創(chuàng)建錯誤,這些錯誤是難以確定的,即,一個對象包含在一個HashMap,但沒有找到。

怎么執(zhí)行OSGi模塊化

<h4 id="adjust-the-generated-getter-and-setter-methods"  font-weight:300;color:#ba3925;text-rendering:optimizelegibility;line-height:1.2;font-size:1.6875em;word-spacing:-0.05em;"="">6.5。調(diào)整生成的getter和setter方法

調(diào)整生成的getter和setter dueDate()字段以進行防御性復制。該Date班是不是一成不變的,我們要避免這種情況的一個實例Todo可以從外部改變,而相應(yīng)的setter。

public Date getDueDate() { return new Date(dueDate.getTime()); }  public void setDueDate(Date dueDate) { this.dueDate = new Date(dueDate.getTime()); }

生成的類應(yīng)該類似于以下列表。

package com.example.e4.rcp.todo.model;  import java.util.Date;  public class Todo {  private final long id; private String summary = ""; private String description = ""; private boolean done = false; private Date dueDate = new Date();  public Todo(long id) { this.id = id; }  public Todo(long id, String summary, String description, boolean done, Date dueDate) { this.id = id; this.summary = summary; this.description = description; this.done = done; setDueDate(dueDate);  }  public long getId() { return id; }  public String getSummary() { return summary; }  public void setSummary(String summary) { this.summary = summary; }  public String getDescription() { return description; }  public void setDescription(String description) { this.description = description; }  public boolean isDone() { return done; }  public void setDone(boolean done) { this.done = done; }  public Date getDueDate() { return new Date(dueDate.getTime()); }  public void setDueDate(Date dueDate) { this.dueDate = new Date(dueDate.getTime()); }  }

6.7。編寫一個copy()方法

將以下copy() 方法添加 到類中。

public Todo copy() { return new Todo(this.id, this.summary, this.description, this.done, getDueDate()); }

6.9。定義模型插件的API

導出com.example.e4.rcp.todo.model包以將其定義為API。

為此,請打開MANIFEST.MF文件并選擇“ 運行時 ”選項卡。添加com.example.e4.rcp.todo.model到導出的包。

怎么執(zhí)行OSGi模塊化

7.1。創(chuàng)建數(shù)據(jù)模型提供程序插件(服務(wù)插件)

創(chuàng)建一個名為com.example.e4.rcp.todo.services的新簡單插件(請參閱命名約定:簡單插件)項目。此插件在以下描述中稱為待辦服務(wù)插件。

MacOS的操作系統(tǒng)踹結(jié)尾的文件夾。服務(wù)特殊,因此我們使用。服務(wù)結(jié)束。

7.3。提供ITodoService接口的實現(xiàn)

com.example.e4.rcp.todo.services.internal 在服務(wù)插件中創(chuàng)建 包并創(chuàng)建以下類。

package com.example.e4.rcp.todo.services.internal;  import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.stream.Collectors;  import com.example.e4.rcp.todo.model.ITodoService; import com.example.e4.rcp.todo.model.Tag; import com.example.e4.rcp.todo.model.Todo;  public class MyTodoServiceImpl implements ITodoService {  private static AtomicInteger current = new AtomicInteger(1); private List todos;  private Tag<tag> rootTag;  public MyTodoServiceImpl() { todos = createInitialModel(); createRootTag(todos); }  @Override public void getTodos(Consumer<List> todosConsumer) { // always pass a new copy of the data todosConsumer.accept(todos.stream().map(t -> t.copy()).collect(Collectors.toList())); }  protected List getTodosInternal() { return todos; }  // create or update an existing instance of Todo @Override public synchronized boolean saveTodo(Todo newTodo) { // hold the Optional object as reference to determine, if the Todo is // newly created or not Optional todoOptional = findById(newTodo.getId());  // get the actual todo or create a new one Todo todo = todoOptional.orElse(new Todo(current.getAndIncrement())); todo.setSummary(newTodo.getSummary()); todo.setDescription(newTodo.getDescription()); todo.setDone(newTodo.isDone()); todo.setDueDate(newTodo.getDueDate());  if (!todoOptional.isPresent()) { todos.add(todo); } return true; }  @Override public Optional getTodo(long id) { return findById(id).map(todo -> todo.copy()); }  @Override public boolean deleteTodo(long id) { Optional deleteTodo = findById(id);  deleteTodo.ifPresent(todo -> { todos.remove(todo); });  return deleteTodo.isPresent(); }  // Example data, change if you like private List createInitialModel() { List list = new ArrayList<>(); list.add(createTodo("Application model", "Flexible and extensible")); list.add(createTodo("DI", "@Inject as programming mode")); list.add(createTodo("OSGi", "Services")); list.add(createTodo("SWT", "Widgets")); list.add(createTodo("JFace", "Especially Viewers!")); list.add(createTodo("CSS Styling", "Style your application")); list.add(createTodo("Eclipse services", "Selection, model, Part")); list.add(createTodo("Renderer", "Different UI toolkit")); list.add(createTodo("Compatibility Layer", "Run Eclipse 3.x")); return list; }  private Todo createTodo(String summary, String description) { return new Todo(current.getAndIncrement(), summary, description, false, new Date()); }  private Optional findById(long id) { return getTodosInternal().stream().filter(t -> t.getId() == id).findAny(); }  }</tag

練習:創(chuàng)建服務(wù)包

8.2。導出服務(wù)插件中的包

com.example.e4.rcp.todo.services 通過“ 運行時 ”選項卡上的MANIFEST.MF 文件 導出 包 ,以便其他插件可用。

請注意,Eclipse工具不支持導出空包。您必須在包中至少創(chuàng)建一個類,然后才能將其導出。

9.1。創(chuàng)建新的捆綁包

通過創(chuàng)建一個新的簡單的插件項目“com.vogella.osgi.firstbundle.internal” 文件  ? 新建  ? 其他...  ? 插件開發(fā)  ? 插件項目。

<h4 id="coding"  font-weight:300;color:#ba3925;text-rendering:optimizelegibility;line-height:1.2;font-size:1.6875em;word-spacing:-0.05em;"="">9.2。編碼

創(chuàng)建以下線程類。

package com.vogella.osgi.firstbundle.internal;  public class MyThread extends Thread { private volatile boolean active = true;  public void run() { while (active) { System.out.println("Hello OSGi console"); try { Thread.sleep(5000); } catch (Exception e) { System.out.println("Thread interrupted " + e.getMessage()); } } }  public void stopThread() { active = false; } }

將Activator.java類更改為以下類。

package com.vogella.osgi.firstbundle;  import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext;  import de.vogella.osgi.firstbundle.internal.MyThread;  public class Activator implements BundleActivator { private MyThread myThread;  public void start(BundleContext context) throws Exception { System.out.println("Starting com.vogella.osgi.firstbundle"); myThread = new MyThread(); myThread.start(); }   public void stop(BundleContext context) throws Exception { System.out.println("Stopping com.vogella.osgi.firstbundle"); myThread.stopThread(); myThread.join(); }  }

9.4。導出您的捆綁包

導出您的捆綁包。這將允許您將其安裝到OSGi運行時。選擇您的捆綁包,然后選擇文件  ? 導出  ? 插件開發(fā)  ?可部署的插件和碎片。

怎么執(zhí)行OSGi模塊化

怎么執(zhí)行OSGi模塊化

取消標記導出源的選項。

怎么執(zhí)行OSGi模塊化

11.關(guān)于本網(wǎng)站

支持免費內(nèi)容

怎么執(zhí)行OSGi模塊化

問題和討論

怎么執(zhí)行OSGi模塊化

教程和代碼許可證

怎么執(zhí)行OSGi模塊化

獲取源代碼

怎么執(zhí)行OSGi模塊化

12.1。vogella GmbH培訓和咨詢支持
訓練 服務(wù)和支持

vogella公司提供 來自Eclipse RCP,Android,Git,Java,Gradle和Spring等領(lǐng)域?qū)<业娜媾嘤柡徒逃?wù)。我們提供公共和內(nèi)部培訓。無論你決定采取什么樣的課程,你都可以在參考之前體驗到許多之前的“我參加的最好的IT類”。

vogella公司提供專家咨詢服務(wù),開發(fā)支持和輔導。我們的客戶范圍從財富100強公司到個人開發(fā)商。

<h3 id="copyright-and-license"  font-weight:300;color:#ba3925;text-rendering:optimizelegibility;line-height:1.2;font-size:2.3125em;word-spacing:-0.05em;letter-spacing:-0.01em;"="">附錄A:版權(quán)和許可

版權(quán)所有&copy;2012-2016 vogella GmbH。免費使用軟件示例是根據(jù)EPL許可證的條款授予的。本教程是根據(jù) Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany許可證發(fā)布的。

關(guān)于怎么執(zhí)行OSGi模塊化就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI