新聞中心
這篇文章將為大家詳細(xì)講解有關(guān)怎么執(zhí)行OSGi模塊化,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
十載的老邊網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營銷網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整老邊建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“老邊網(wǎng)站設(shè)計(jì)”,“老邊網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
OSGi模塊化 -
Lars Vogel,Simon Scholz(c)2008,2017 vogella GmbH版本5.2,202.02.2017
目錄
OSGi簡介軟件模塊化
無激活劑
對(duì)用戶界面沒有貢獻(xiàn)
不是一個(gè)富客戶端應(yīng)用程序
生成時(shí)沒有模板
1.2。OSGi規(guī)范和OSGi實(shí)現(xiàn)
OSGi是一組規(guī)范,在其核心規(guī)范中定義了Java的組件和服務(wù)模型。OSGi的實(shí)際優(yōu)點(diǎn)是每個(gè)軟件組件可以通過一組導(dǎo)出的Java包來定義其API,并且每個(gè)組件可以指定其所需的依賴性。
組件和服務(wù)可以被動(dòng)態(tài)地安裝,激活,去激活,更新和卸載。
OSGi規(guī)范有幾個(gè)實(shí)現(xiàn),例如Eclipse Equinox,Knopflerfish OSGi或Apache Felix。
Eclipse Equinox是基本OSGi規(guī)范的參考實(shí)現(xiàn)。它也是Eclipse應(yīng)用程序所基于的運(yùn)行時(shí)環(huán)境。
1.4。命名約定:簡單的插件
一個(gè)插件可以通過Eclipse中通過生成文件 ? 新建 ? 其他... ? 插件開發(fā) ? 插件工程菜單項(xiàng)。相應(yīng)的向?qū)г试S指定多個(gè)選項(xiàng)。此腳本調(diào)用使用以下選項(xiàng)生成的插件:簡單插件或簡單包。
2.1。清單文件(MANIFEST.MF)
技術(shù)上OSGi插件是 帶有附加元信息的.jar文件。此元信息存儲(chǔ)在 META-INF / MANIFEST.MF 文件中。此文件稱為 清單 文件,是標(biāo)準(zhǔn)Java規(guī)范的一部分,OSGi向其中添加了額外的元數(shù)據(jù)。根據(jù)Java規(guī)范,任何Java運(yùn)行時(shí)必須忽略未知的元數(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
下表說明了清單文件中的標(biāo)識(shí)符。有關(guān)OSGi中通常使用的版本模式的信息,請(qǐng)參閱使用OSGi進(jìn)行語義版本控制。
標(biāo)識(shí)符 | 描述 |
---|---|
軟件包名稱 | 插件的簡短描述。 |
Bundle-SymbolicName | 插件的唯一標(biāo)識(shí)符。如果此插件使用Eclipse的擴(kuò)展點(diǎn)功能,則必須將其標(biāo)記為Singleton。您可以通過在Bundle-SymbolicName標(biāo)識(shí)符之后添加以下語句來實(shí)現(xiàn): ; singleton:=true |
Bundle-Version | 定義插件版本,如果發(fā)布了插件的新版本,則必須遞增。 |
Bundle-Activator | 定義實(shí)現(xiàn)接口的可選激活器類BundleActivator。該類的實(shí)例在插件被激活時(shí)創(chuàng)建。無論何時(shí)啟動(dòng)或停止插件,都會(huì)調(diào)用它start()和stop()方法。OSGi激活器可用于在啟動(dòng)期間配置插件。激活程序的執(zhí)行會(huì)增加應(yīng)用程序的啟動(dòng)時(shí)間,因此應(yīng)謹(jǐn)慎使用此功能。 |
Bundle-RequiredExecutionEnvironment(BREE) | 指定運(yùn)行插件所需的Java版本。如果不滿足此要求,則OSGi運(yùn)行時(shí)不會(huì)加載插件。 |
Bundle-ActivationPolicy | 將此設(shè)置為 延遲 將告訴OSGi運(yùn)行時(shí),只有當(dāng)其插件之一(即類和接口)被其他插件使用時(shí),才會(huì)激活該插件。如果未設(shè)置,Equinox運(yùn)行時(shí)不會(huì)激活插件,即,此插件提供的服務(wù)不可用。 |
Bundle-ClassPath | Bundle-ClassPath指定從bundle加載類的位置。默認(rèn)值為“。”。它允許從bundle的根加載類。您還可以向其中添加JAR文件,這些文件稱為 嵌套JAR文件。 |
2.3。使用OSGi的語義版本化
OSGi建議對(duì) 通過 字段標(biāo)識(shí)符定義的版本號(hào)使用 。。模式 Bundle-Version。如果更改插件代碼,請(qǐng)根據(jù)以下規(guī)則集增加版本。
如果所有更改都向后兼容,則會(huì)增加。
如果公共API已更改,但所有更改都向后兼容,則增加。
如果更改不向后兼容,則會(huì)增加。
有關(guān)此版本方案的更多信息,請(qǐng)參閱 Eclipse版本編號(hào)Wiki。
2.5。插件的生命周期在OSGi
通過在OSGi運(yùn)行時(shí)中安裝插件,插件將保留在本地bundle緩存中。OSGi運(yùn)行時(shí)然后嘗試解析它的依賴關(guān)系。
如果解決了所有必需的依賴關(guān)系,則插件位于
RESOLVED 狀態(tài),否則它保持在 INSTALLED 狀態(tài)。
在存在可以滿足依賴性的幾個(gè)插件的情況下,使用具有最高有效版本的插件。
如果版本相同,則使用具有最低唯一標(biāo)識(shí)符(ID)的插件。每個(gè)插件都會(huì)在安裝期間獲取框架分配的此ID。
插件啟動(dòng)時(shí),其狀態(tài)為 STARTING。成功啟動(dòng)后,它將變?yōu)?nbsp;ACTIVE。
此生命周期如下圖所示。
3.插件的API定義
在MANIFEST.MF文件中,插件還通過導(dǎo)出包標(biāo)識(shí)符定義其API。未顯式導(dǎo)出的所有軟件包對(duì)其他插件不可見。
所有這些限制都通過特定的OSGi實(shí)施classloader。每個(gè)插件都有自己的類加載器。不使用reflection.s不能訪問受限類
不幸的是,OSGi不能阻止你使用Java反射來訪問這些類。這是因?yàn)镺SGi基于尚不支持模塊化層的Java運(yùn)行時(shí)。
通過x-internal標(biāo)志,OSGi運(yùn)行時(shí)可以將導(dǎo)出的包標(biāo)記為臨時(shí)。這允許其他插件使用相應(yīng)的類,但表示這些類不被視為官方API。
以下屏幕截圖顯示如何x-internal在清單編輯器中設(shè)置包。
這是相應(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編輯器如何顯示臨時(shí)API的使用。這種訪問可以被配置為顯示為,錯(cuò)誤,警告或者如果這種訪問應(yīng)當(dāng)不導(dǎo)致附加消息。
默認(rèn)值為顯示警告消息。您可以通過Eclipse的喜好調(diào)整這個(gè)窗口 ? 首選項(xiàng) ? 的Java ? 編譯器 ? 錯(cuò)誤/警告首選項(xiàng)設(shè)置。
您可以定義一組插件可以訪問臨時(shí)API,而不會(huì)出現(xiàn)警告或錯(cuò)誤消息。這可以通過x-friends指令完成。如果您在清單編輯器的“ 運(yùn)行時(shí) ”選項(xiàng)卡上的“ 包可見性”部分添加插件,則會(huì)添加此標(biāo)志。
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è)置中提到的所有插件都可以訪問包,而不會(huì)收到錯(cuò)誤或警告消息。
4.1。OSGi控制臺(tái)
OSGi控制臺(tái)就像一個(gè)命令行shell。在此控制臺(tái)中,您可以鍵入命令以執(zhí)行OSGi操作。這可以用于分析應(yīng)用程序的OSGi層上的問題。
例如,使用命令 ss 獲取所有包的概述,它們的狀態(tài)和bundle-id。下表是最重要的OSGi命令的參考。
命令 | 描述 |
---|---|
help | 列出可用的命令。 |
ss | 列出安裝的軟件包及其狀態(tài)。 |
ss vogella | 列出捆綁包及其在其名稱中包含vogella的狀態(tài)。 |
start | 使用 ID 啟動(dòng)包。 |
stop | 使用 ID 停止捆綁。 |
diag | 診斷特定包。它列出所有缺失的依賴項(xiàng)。 |
install URL | 從URL安裝包。 |
uninstall | 使用 ID 卸載捆綁軟件。 |
bundle | 顯示具有 ID的捆綁包的信息,包括已注冊和已使用的服務(wù)。 |
headers | 顯示包的MANIFST.MF信息。 |
services filter | 顯示所有可用的服務(wù)及其消費(fèi)者。過濾器是一個(gè)可選的LDAP過濾器,例如,查看提供ManagedService實(shí)現(xiàn)的所有服務(wù)使用“services(objectclass = * ManagedService)”命令。 |
4.3。Telnet
如果 在啟動(dòng)配置中指定 -console參數(shù),Eclipse將允許您與OSGi控制臺(tái)交互。默認(rèn)情況下,使用Eclipse IDE創(chuàng)建的OSGi啟動(dòng)配置包含此參數(shù)。通過以下參數(shù),您可以打開一個(gè)端口,您可以通過telnet協(xié)議連接到該端口。
-console 5555
如果打開到OSGi控制臺(tái)的telnet會(huì)話,您可以使用tab完成和類似于 Linux下的Bash shell 的命令歷史記錄 。
5.下載Eclipse SDK
如果您計(jì)劃向Eclipse平臺(tái)添加功能,則應(yīng)下載最新的Eclipse版本。官方版本具有穩(wěn)定的API,因此是添加插件和功能的良好基礎(chǔ)。
Eclipse IDE提供了不同的版本。雖然可以在任何Eclipse包中安裝必要的工具,但通常更容易下載Eclipse Standard發(fā)行版,其中包含插件開發(fā)的所有必要工具。其他軟件包增加了Eclipse插件開發(fā)不需要的更多工具。
瀏覽到Eclipse下載站點(diǎn)并下載Eclipse Standard軟件包。
Eclipse 4.5還提供了一個(gè)新的Eclipse安裝程序安裝程序。如果您要下載多種版本的Eclipse,安裝程序?qū)⒎浅S杏茫驗(yàn)樗褂霉蚕戆惭b池用于常用插件。 |
6.1。為數(shù)據(jù)模型創(chuàng)建插件
創(chuàng)建一個(gè)名為com.example.e4.rcp.todo.model的簡單插件項(xiàng)目(請(qǐng)參閱命名約定:簡單插件)。
以下屏幕截圖描述了插件項(xiàng)目向?qū)У牡诙摷捌湎鄳?yīng)的設(shè)置。按此頁上的完成按鈕,以避免使用模板。
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)錯(cuò)誤。此錯(cuò)誤在下一節(jié)中解決。 |
6.4。生成getter和setter方法
使用來源 ? 生成getter和setter ...菜單來創(chuàng)建getter和setter方法為您的字段。
為什么id字段標(biāo)記為final? 該ID是終局的,因此Eclipse將創(chuàng)建只有一個(gè)getter。這是正確和希望的。我們將使用此字段來生成equals和hashCode()方法,因此它不應(yīng)該是可變的。更改這是在使用的字段equals和hashCode()方法可以創(chuàng)建錯(cuò)誤,這些錯(cuò)誤是難以確定的,即,一個(gè)對(duì)象包含在一個(gè)HashMap,但沒有找到。 |
6.5。調(diào)整生成的getter和setter方法
調(diào)整生成的getter和setter dueDate()字段以進(jìn)行防御性復(fù)制。該Date班是不是一成不變的,我們要避免這種情況的一個(gè)實(shí)例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。編寫一個(gè)copy()方法
將以下copy() 方法添加 到類中。
public Todo copy() { return new Todo(this.id, this.summary, this.description, this.done, getDueDate()); }
6.9。定義模型插件的API
導(dǎo)出com.example.e4.rcp.todo.model包以將其定義為API。
為此,請(qǐng)打開MANIFEST.MF文件并選擇“ 運(yùn)行時(shí) ”選項(xiàng)卡。添加com.example.e4.rcp.todo.model到導(dǎo)出的包。
7.1。創(chuàng)建數(shù)據(jù)模型提供程序插件(服務(wù)插件)
創(chuàng)建一個(gè)名為com.example.e4.rcp.todo.services的新簡單插件(請(qǐng)參閱命名約定:簡單插件)項(xiàng)目。此插件在以下描述中稱為待辦服務(wù)插件。
MacOS的操作系統(tǒng)踹結(jié)尾的文件夾。服務(wù)特殊,因此我們使用。服務(wù)結(jié)束。 |
7.3。提供ITodoService接口的實(shí)現(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 TagrootTag; public MyTodoServiceImpl() { todos = createInitialModel(); createRootTag(todos); } @Override public void getTodos(Consumer 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(); } }
練習(xí):創(chuàng)建服務(wù)包
8.2。導(dǎo)出服務(wù)插件中的包
com.example.e4.rcp.todo.services 通過“ 運(yùn)行時(shí) ”選項(xiàng)卡上的MANIFEST.MF 文件 導(dǎo)出 包 ,以便其他插件可用。
請(qǐng)注意,Eclipse工具不支持導(dǎo)出空包。您必須在包中至少創(chuàng)建一個(gè)類,然后才能將其導(dǎo)出。 |
9.1。創(chuàng)建新的捆綁包
通過創(chuàng)建一個(gè)新的簡單的插件項(xiàng)目“com.vogella.osgi.firstbundle.internal” 文件 ? 新建 ? 其他... ? 插件開發(fā) ? 插件項(xiàng)目。
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。導(dǎo)出您的捆綁包
導(dǎo)出您的捆綁包。這將允許您將其安裝到OSGi運(yùn)行時(shí)。選擇您的捆綁包,然后選擇文件 ? 導(dǎo)出 ? 插件開發(fā) ?可部署的插件和碎片。
取消標(biāo)記導(dǎo)出源的選項(xiàng)。
11.關(guān)于本網(wǎng)站
支持免費(fèi)內(nèi)容
問題和討論
教程和代碼許可證
獲取源代碼
12.1。vogella GmbH培訓(xùn)和咨詢支持
訓(xùn)練 | 服務(wù)和支持 |
---|---|
vogella公司提供 來自Eclipse RCP,Android,Git,Java,Gradle和Spring等領(lǐng)域?qū)<业娜媾嘤?xùn)和教育服務(wù)。我們提供公共和內(nèi)部培訓(xùn)。無論你決定采取什么樣的課程,你都可以在參考之前體驗(yàn)到許多之前的“我參加的最好的IT類”。 | vogella公司提供專家咨詢服務(wù),開發(fā)支持和輔導(dǎo)。我們的客戶范圍從財(cái)富100強(qiáng)公司到個(gè)人開發(fā)商。 |
附錄A:版權(quán)和許可
版權(quán)所有©2012-2016 vogella GmbH。免費(fèi)使用軟件示例是根據(jù)EPL許可證的條款授予的。本教程是根據(jù) Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany許可證發(fā)布的。
關(guān)于怎么執(zhí)行OSGi模塊化就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
本文名稱:怎么執(zhí)行OSGi模塊化
鏈接分享:http://www.ef60e0e.cn/article/iigeod.html