在讀本文之前,您應(yīng)該對(duì)基于Equinox的開(kāi)發(fā)有一定的了解,如果您還不太清楚,請(qǐng)參考基于Equinox開(kāi)發(fā)HelloWorld一文。 本文講到的例子是仿照網(wǎng)上甚為流行的一個(gè)例子,但苦于一直未找到源碼,網(wǎng)上貼的都是一些轉(zhuǎn)帖,代碼片段,估計(jì)初學(xué)者很難將其還原并調(diào)通!我最開(kāi)始弄這個(gè)咚咚的時(shí)候,其過(guò)程之痛苦,難以言喻,所以想著仿照該例子的設(shè)計(jì),給予實(shí)現(xiàn),文后貼出源碼,希望能幫到大家。 該例子是一個(gè)關(guān)于計(jì)算器的實(shí)例,osgi.example.compute bundle(下文簡(jiǎn)稱compute bundle)提供了統(tǒng)一的計(jì)算接口:Compute,另外兩個(gè)bundle分別為osgi.example.compute.add(下文簡(jiǎn)稱add bundle)和osgi.example.compute.multiply(下文簡(jiǎn)稱multiply bundle),在這兩個(gè)bundle中,各自對(duì)compute bundle進(jìn)行不同的實(shí)現(xiàn),一個(gè)實(shí)現(xiàn)加法,一個(gè)實(shí)現(xiàn)乘法。另外還有一個(gè)服務(wù)消費(fèi)者osgi.example.compute.consumer bundle(下文簡(jiǎn)稱consumer bundle),consumer bundle負(fù)責(zé)消費(fèi)add bundle和multiply bundle提供的服務(wù)。上述4個(gè)bundle之間的關(guān)系如下圖所示:
創(chuàng)建4個(gè)bundle之后的工程目錄如下圖所示:
通過(guò)該示例,將演示如何利用Spring DM發(fā)布和調(diào)用OSGi服務(wù),同時(shí)還將演示OSGi的動(dòng)態(tài)服務(wù)調(diào)用能力。 1. bundle osgi.example.compute compute bundle只提供一個(gè)接口——Compute,因此無(wú)需依賴更多的bundle,只需最基本的osgi即可。因?yàn)椴簧婕白?cè)資源之類(lèi)的,所以也無(wú)需Activator入口類(lèi)。 Computer接口源代碼如下所示:
add bundle是對(duì)compute bundle的具體服務(wù)實(shí)現(xiàn),在MANIFEST.MF文件需要引入osgi.example.compute包;當(dāng)然也可以通過(guò)添加依賴bundle的形式,即不引入包,而直接在Required Plug-ins中添加compute bundle。如下圖所示:
注意:OSGi官方指出,當(dāng)需要用到其他bundle的類(lèi)型時(shí),不提倡依賴bundle,應(yīng)該盡可能采用Import-package的方式引入包,因?yàn)橐蕾?span style="color: #ff0000">bundle可能在加載bundle的時(shí)候發(fā)生問(wèn)題。
通過(guò)引入osgi.example.compute包,osgi.example.compute bundle被加到了add bundl的classpath當(dāng)中,解決了開(kāi)發(fā)時(shí)期的類(lèi)型識(shí)別問(wèn)題。 這樣一來(lái),在add bundle中就能使用compute bundle中的接口了,Computer接口的實(shí)現(xiàn)如下:
Compute的實(shí)現(xiàn)已經(jīng)實(shí)現(xiàn)了,那么如何將其發(fā)布出去呢?這個(gè)是由Spring DM負(fù)責(zé),Spring DM利用OSGi命名空間下的<service>元素將bean導(dǎo)出為OSGi服務(wù)。最簡(jiǎn)單的形式為:
從示例中可以看出,beanToPublish被service元素聲明導(dǎo)出。 另外,service結(jié)點(diǎn)還有一些高級(jí)屬性,如depends-on、context-class-loader、ranking等待,詳情請(qǐng)看spring dm reference。 首先,需要在add bundle的工程根目錄下的”META-INF”的文件夾下創(chuàng)建一個(gè)文件夾,取名”spring”,Spring DM能夠自動(dòng)解析該文件夾下所有的spring配置文件。spring配置文件的具體內(nèi)容如下所示:
該bundle和add bundle相似,在這就不贅述了。 4. bundle osgi.example.compute.client
顧名思義,該bundle將作為add 、multiply兩個(gè)bundle的客戶bundle,演示如何導(dǎo)入服務(wù)。 OSGi的測(cè)試工作比較麻煩,這方面還沒(méi)研究,在這里利用spring實(shí)例化bean的時(shí)期,從構(gòu)造函數(shù)入手,對(duì)服務(wù)進(jìn)行測(cè)試。Client類(lèi)的實(shí)現(xiàn)很簡(jiǎn)單,如下所示:
另外,因?yàn)閏lient用到了其他幾個(gè)bundle的類(lèi)型,所以需要導(dǎo)入相應(yīng)的包,步驟在上面已有講到。 spring dm靠<reference>元素來(lái)引入服務(wù),最簡(jiǎn)單的形式如下所示:
如果需要用到該服務(wù),如某個(gè)bean包含一個(gè)com.xyz.MessageService屬性,則配置該bean如下所示:
需要勾選中spring bundle版(2.5.6),spring dm的幾個(gè)核心包:core、extender、io再點(diǎn)validate bundles按鈕,校驗(yàn)是否已全部選中其依賴的bundle。然后即可點(diǎn)擊運(yùn)行了。 運(yùn)行之后,我們發(fā)現(xiàn)控制臺(tái)輸出結(jié)果: The Sum is---11 通過(guò)ss命令,如下: 5 ACTIVE osgi.example.compute.multiply_1.0.0 6 ACTIVE osgi.example.compute.add_1.0.0 7 ACTIVE osgi.example.compute.client_1.0.0 將6停掉:stop 6 然后再refresh 7,控制臺(tái)輸出如下結(jié)果: The Multiply is---30 通過(guò) ss 命令,如下: 5 ACTIVE osgi.example.compute.multiply_1.0.0 6 RESOLVED osgi.example.compute.add_1.0.0 7 ACTIVE osgi.example.compute.client_1.0.0 現(xiàn)在multiply處于運(yùn)行狀態(tài),而add已經(jīng)被停止,所以client導(dǎo)入的服務(wù)實(shí)際是由multiply提供的。
6. 總結(jié)
通過(guò)該文檔,我們已經(jīng)清楚了,如何使用Spring DM導(dǎo)出、導(dǎo)入服務(wù)。Spring DM的一些高級(jí)特性請(qǐng)查閱spring dm reference。 附件:osgi.example.compute.rar