在Spring DM中使用Annotations發布和引用OSGi服務

fmms 12年前發布 | 100K 次閱讀 OSGi

Spring DM并不是OSGi規范的實現,也就是說它不是OSGi容器。它只是一套用于在 OSGi環境中將Spring Bean注冊發布為OSGi服務的工具。它充分利用Spring的特性,將OSGi與Spring無縫的加以結合,實現了Spring的模塊化開發。

1.  在使用Spring DM進行開發過程中發現的問題:

雖然Spring DM改進了OSGi原本的DS開發,使用Spring Bean來完成服務的注冊。但是對于“懶惰”的程序員來說還是太過繁瑣,首先需要在XML中注冊SpringBean,然后要使用SpringDM提供的 特殊命名空間( )發布服務,最后當需要引入一個OSGi服務時又要使用SpringDM提供的另外一個特殊命名 空間( )來引入服務。對于一個只有十幾個Bean的應用程序來說,這些配置量也無所謂,但是當應用程序的 Bean發展到上百個的時候,這簡直就是配置噩夢。尤其是在多人合作開發的環境下,經常會發生遺漏配置的情況,一旦遺漏則OSGi服務將無法啟動,并且要 在上百個Bean配置XML文件中查找到底是哪個遺漏了,的確也是一件體力活(這正是IT民工的悲慘命運)。

當然Spring DM的開發團隊也想到了這點,為我們開發人員提供了Annotation的選項,這樣可以大大減少XML的配置量(這里我們不爭論XML和 Annotation孰優孰劣)。但是不知為何,Spring DM只提供了引入服務的Annotation,并沒有提供發布OSGi服務的Annotation,這讓我很費解?其次,由于SpringDM是在 JDK1.4環境下編譯的,所以默認情況下Annotation的功能是Disabled的。這又讓我很費解?到底讓我們用不用Annotation!

2.  問題的解決方案:

針對上述的問題,我們可以通過以下方法解決;

1)  如何啟用Spring DM的Annotation功能

通過閱讀Spring DM提供的官方文檔,讓我很莫名,關于Annotation的介紹只有寥寥數語,而且還是放在附錄中介紹的。可能是我的英文水平太爛,總之一句話,沒看 懂!后來從解決其他問題的過程中得到了啟示,終于開啟了SpringDM的Annotation功能。

第一步,創建一個Fragment類型的Bundle,具體的目錄結構如下圖所示:

在Spring DM中使用Annotations發布和引用OSGi服務

這里主要關注2個文件,一個是extender.xml文件和MANIFEST.MF文件。

第二步,創建extender.xml文件:

在上圖所示的目錄結構中創建一個extender.xml文件,這個文件用于覆蓋SpringDM Extender的配置選項。因為默認情況下是不支持Annotation的,所以要將指定的屬性值設置為開啟狀態,才能使用Annotation功能。 配置文件的內容如下:

在Spring DM中使用Annotations發布和引用OSGi服務

這個配置文件其實就是一個Spring Bean的配置文件。將process.annotations屬性設置成true,就開啟了Spring DM的Annotation功能。

第三步,創建MANIFEST.MF文件,這個文件是Bundle的屬性配置文件,我們在這個文件中指定Fragment-Host屬性,具體內容如下:

在Spring DM中使用Annotations發布和引用OSGi服務

其中我們要關注的是Fragment-Host屬性,這里指定為 org.springframework.osgi.extender,表示在extender Bundle啟動之前先啟動ftps-extender-config這個Bundle,這樣就將默認的屬性值更新為我們設置的屬性值。

第四步,在Spring的XML配置文件中注冊處理Annotation的處理器Bean,如下所示:

在Spring DM中使用Annotations發布和引用OSGi服務

通過上述4個步驟,我們就開啟了Spring DM的Annotation功能。

以下例子展示如何使用Spring DM的Annotation功能:

在Spring DM中使用Annotations發布和引用OSGi服務

其中@ServiceReference就是引入OSGi服務的Annotation,它等效于XML中的 配置項。

2)  編寫自己的Annotation實現OSGi服務的發布:

勝利的喜悅還沒維持多久,新的問題又隨之而來。既然我們已經有引入OSGi服務的Annotation,為什么發布OSGi服務的時候不能使用 Annotation呢?我們仍然在繼續編寫一大坨苦澀的OSGi配置項,這種工作即枯燥又乏味。但是尋遍SpringDM的所有官方文檔,包括 SpringDM提供的Annotation擴展包源代碼,都沒有找到發布OSGi服務的Annotation。Google一下,大致都是提問的,沒有 回答問題的。沒有辦法,只能靠自己。經過對SpringDM源代碼的閱讀以及使用BEBUG來查看代碼流程的走向,終于了解了SpringDM將 Spring Bean發布為OSGi服務的大致方法。其中最關鍵的對象就是:OsgiServiceFactoryBean。這個工廠bean就是將 SpringBean發布為OSGi服務的關鍵類。這個類并不難懂,有興趣的朋友可以閱讀一下這個類的源代碼。由于我們是解決問題的文章,不是談理論的文 章,所以我們繼續看實現方案:

首先介紹一下解決方案的大致流程。1)通過編寫一個實現了BeanPostProcessor接口的處理器類,我們就可以對Bean的生命周期進行 控制。2)在容器中的某個Bean被初始化之后,我們攔截這個Bean,并獲取該Bean上是否寫了注冊OSGi服務的Annotation。3)如果 是,則實例化OsgiServiceFactoryBean對象,設置相關的屬性值,并調用OsgiServiceFactoryBean對象的 afterPropertiesSet方法,進行OSGi服務的注冊和發布。最后返回該OsgiServiceFactoryBean對象。同時將該對象 的引用放入一個集合中保存用于OSGi服務的注銷。4)當處理器類被銷毀時,對集合中的所有OsgiServiceFactoryBean對象執行 destroy方法,完成OSGi服務的注銷操作。

先來看Annotation的代碼,很簡單,如下所示:

在Spring DM中使用Annotations發布和引用OSGi服務

ElementType.TYPE指定這個Annotation只能用于類聲明,接口聲明上。

接著是處理器的實現代碼,先關注類簽名:

在Spring DM中使用Annotations發布和引用OSGi服務

這里需要關注的是實現的幾個接口的用途。實現BundleContextAware接口是為了在處理器中獲取Bundle上下文對象。實現 BeanClassLoaderAware接口是為了在處理器中獲取ClassLoader對象,這些對象都是注冊發布OSGi服務所必須使用的對象。而 繼承InstantiationAwareBeanPostProcessorAdapter適配器是為了在Spring Bean初始化完之后給我們一個機會進行定制的特殊處理。我們需要覆蓋的是 InstantiationAwareBeanPostProcessorAdapter類的 postProcessAfterInitialization方法。該方法在Spring Bean初始化之后執行。我們來看這個方法的實現,如下所示:

在Spring DM中使用Annotations發布和引用OSGi服務

代碼中的注釋已經很好的說明了各邏輯塊的實現目的,不再贅述。其中需要關注createExporter方法,這個方法是創建OsgiServiceFactoryBean對象的。如下所示:

在Spring DM中使用Annotations發布和引用OSGi服務

代碼很簡單,就是實例化對象,并調用注冊發布OSGi服務的方法。其實發布一個OSGi服務只需要三個參數:Bean名稱,Bean對象,Bean實現接口類型的數組,這個和XML中的配置屬性一一對應:

其中ref屬性對應Bean名稱以及一個Bean對象的引用,interface屬性對應Bean實現接口類型的一個數組。

該方法中用到的一些其他實例變量的定義如下:

在Spring DM中使用Annotations發布和引用OSGi服務

最后來看一下OSGi服務的注銷實現,代碼如下:

在Spring DM中使用Annotations發布和引用OSGi服務

注銷服務就是將先前注冊時保存下來的OsgiServiceFactoryBean對象集合進行destroy方法的調用。

3.  啟用發布OSGi服務的Annotation:

相比較開啟SpringDM自帶的Annotation,我們這個Annotation的啟用方法要簡單的多。只要在Spring的XML中注冊這個處理器Bean就可以了,代碼如下:

在Spring DM中使用Annotations發布和引用OSGi服務

以下實例代碼展示了如何使用使用Annotation發布一個OSGi服務發布:

在Spring DM中使用Annotations發布和引用OSGi服務

其中@OsgiService就是注冊發布OSGi服務的Anntation。到此我們終于實現了使用Annotation來發布注冊OSGi服務 以及引入OSGi服務,我們不再需要在XML中配置那一大坨無聊的OSGi服務配置了。最后引用一句名言:任何發明創造源自于“懶惰”。

轉自:CSDN

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!