OSGi是在Java中定義動態模塊的方法。 主要為Java實現的三個OSGi容器是Apache Felix , Eclipse Equinox和Knopflefish 。
為什么選擇OSGi? 因為OSGi提供了將應用程序劃分為多個模塊的能力,并且那些模塊易于與其他依賴項一起管理。 除此之外,它非常容易安裝,更新,停止和刪除沒有停止引擎的模塊(例如:Tomcat Web應用程序容器)。 我們可以使用多種實現方式來影響其他參考。
基于Web的Java框架主要有3個層(表示層,業務層和DAO層)。 在那里,我們可以將其分為三個基于OSGi的模塊。 那么我們可以很容易地將錯誤修復到一層,而不會影響其他錯誤并重新啟動我們的Web容器。 只是我們需要更新模塊。
在OSGi世界中,輸出是捆綁包,可以是Jar或War文件。 捆綁軟件由Java類和其他資源以及一些其他元數據組成(向其他捆綁軟件提供服務和軟件包)。
我將使用Eclipse IDE創建我的第一個捆綁軟件。 因為Eclipse IDe內置了Equinox容器(每個eclipse插件都是OSGi捆綁包)。
創建Eclipse插件項目
- 轉到新建–>其他–>插件項目 ,然后單擊下一步,將出現新項目創建對話框
- 提供項目名稱和目標平臺,如下所示。 然后點擊下一步
項目名稱: com.chandana.Hello.HelloWorld
目標平臺:選擇Stranded OSGi

- 在下一個屏幕中,您可以更改捆綁包信息(這些信息可在MANIFEST.MF中找到,稍后我會提供詳細信息),然后單擊“下一步”按鈕。

- 之后將出現OSGi項目模板選擇對話框。選擇Hello OSGi Bundle,然后單擊Finish。
-
幾秒鐘后,Eclipse將生成Hello World Plug-In-Project(我幾秒鐘沒有響應:))
在我的項目結構中是這樣的:

Activator.java
package com.chandana.hello.helloworld;import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;public class Activator implements BundleActivator {/** (non-Javadoc)* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)*/public void start(BundleContext context) throws Exception {System.out.println("Hello World!!");}/** (non-Javadoc)* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)*/public void stop(BundleContext context) throws Exception {System.out.println("Goodbye World!!");}}
Activator是實現BundleActivator的類 接口。 它已經停了 然后開始 方法。 ? 當捆綁包啟動或停止時,將調用這些方法 。 此束激活器類在MENIFEST.MF文件( 束激活器條目)中指定。
啟動方法:
捆綁包啟動時,OSGi容器將調用start方法。 我們可以使用此啟動方法進行初始化的數據庫連接,注冊服務以供其他捆綁使用。 停止方式: 捆綁包停止時,OSGi容器調用stop方法。 我們可以使用此方法從服務注冊表中刪除服務,例如清理過程
清單文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HelloWorld
Bundle-SymbolicName: com.chandana.Hello.HelloWorld
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.chandana.hello.helloworld.Activator
Bundle-Vendor: CHANDANA
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0"
Bundle-ManifestVersion
Bundle-ManifestVersion標頭顯示OSGi容器,該捆綁包遵循OSGi規范的規則。 值為2表示捆綁軟件符合OSGi規范第4版。 值1表示它符合版本3或更早的版本。
捆綁名稱
Bundle-Name標頭定義捆綁的簡短可讀名稱。
Bundle-SymbolicName
Bundle-SymbolicName標頭指定捆綁包的唯一名稱。 這是您在從其他捆綁包中引用給定捆綁包時將使用的名稱。
捆綁版本
Bundle-Version標頭是捆綁軟件的版本號。
捆綁銷售商
Bundle-Vendor標頭是供應商的描述(例如,這是我的名字)。
進口包裝
Import-Package指示此捆綁包還需要其他Java捆綁包(OSGi)。 我們稱之為依賴性。
出口包裝
導出包指示什么是捆綁包中的公共包,那些導出包可以從其他捆綁包中導入。
運行捆綁包:
- 對于“運行此項目”,請單擊“運行”->“運行配置”,在OSGi Framework中,右鍵單擊并創建新的“運行配置”。

- 首先取消選中所有目標平臺,然后單擊“ 添加必需的捆綁包” 。
- 之后,單擊“運行”按鈕,應用更改并運行項目。
- 運行后,項目OSGi控制臺顯示如下。

OSGi終端命令:
源代碼
接下來,我將描述如何創建基于依賴的OSGi捆綁軟件。
OSGi服務是一個Java對象實例,已向OSGi框架注冊了一組屬性。 可以通過服務注冊表(通過類BundleContext執行)訪問服務。 BundleActivator將在啟動和停止時調用。 當BundleActivator調用start方法時,我們將注冊我們的服務。 之后,任何捆綁包都可以訪問該服務。
服務包:
在服務包中,您需要導出服務,并需要通過服務注冊表進行注冊。 當我們導出服務時,我們僅導出接口包。 與往常一樣,這是從其他捆綁包中隱藏實現。
我已經創建了一個名為HelloService的示例OSGi項目。
清單文件
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HelloService
Bundle-SymbolicName: com.chandana.hello.HelloService
Bundle-Version: 1.0.0
Bundle-Activator: com.chandana.hello.helloservice.Activator
Bundle-Vendor: CHANDANA
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: com.chandana.hello.service
Bundle-ActivationPolicy: lazy
服務接口:
public interface HelloService { public String helloMethods();
}
服務實施:
public class HelloServiceImpl implements HelloService {@Overridepublic String helloMethods() {String retValue = "Inside Hello Service method";return retValue;}
}
邊界激活劑:
public class Activator implements BundleActivator {ServiceRegistration serviceRegistration;/** (non-Javadoc)* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)*/public void start(BundleContext context) throws Exception {System.out.println("Bundle Started.....!!!!!");HelloService service = new HelloServiceImpl();serviceRegistration = context.registerService(HelloService.class.getName(), service,null);}/** (non-Javadoc)* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)*/public void stop(BundleContext context) throws Exception {System.out.println("Bundle Stoped.....!!!!!");serviceRegistration.unregister();}
}
使用發布的服務時,可以從另一個捆綁包中導入它。 因此需要為HelloClient創建另一個插件項目
捆綁內容
捆綁包上下文是OSGi運行時中單個捆綁包的上下文,它是在捆綁包啟動時創建的。 捆綁包上下文可用于安裝新捆綁包,通過其他捆綁包獲取注冊的服務以及在框架中注冊服務。
清單文件
Import-Package: org.osgi.framework;version="1.3.0",com.chandana.hello.service
導入捆綁軟件后,您可以訪問該服務。 重要的是只能通過bundle上下文訪問服務。 您可以通過BundleContext.getService()方法獲取實際的服務對象。
激活器類:
public class Activator implements BundleActivator {ServiceReference serviceReference; /** (non-Javadoc)* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)*/public void start(BundleContext context) throws Exception {serviceReference= context.getServiceReference(HelloService.class.getName());HelloService helloService =(HelloService)context.getService(serviceReference);System.out.println(helloService.helloMethods());}/** (non-Javadoc)* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)*/public void stop(BundleContext context) throws Exception {context.ungetService(serviceReference);}
}
context.getServiceReference()方法返回HelloService OSGi服務引用,使用該服務引用可以訪問實際的服務對象。
對于“運行此項目”,請單擊“ 運行”->“運行配置” ,在OSGi Framework中,右鍵單擊并創建新的“運行配置” 。 確保HelloService和HelloClient 。
問題 :
如果客戶端訪問服務時未啟動服務,會發生什么情況?
如果您停止了該服務捆綁包,會發生什么?
代碼倉庫 :
http://code.google.com/p/osgi-world/source/browse/#svn/trunk/com.chandana.hello.HelloService
http://code.google.com/p/osgi-world/source/browse/#svn/trunk/com.chandana.hello.HelloClient
參考:來自JCG合作伙伴的 OSGi(Java模塊化) 簡介和OSGi – 2(OSGi服務)簡介 ? Chandana Napagoda博客上的Chandana Napagoda 。
翻譯自: https://www.javacodegeeks.com/2012/01/introduction-to-osgi-modular-java.html