【51CTO精選譯文】本文是《你好,OSGi》系列的第八部分。在之前一篇已經使用Spring DM創建了Hello World應用,下面的步驟就是要進行服務套件的導入和導出了。簡單來說就是,構建一個面向服務的聯絡管理應用程序。
51CTO編輯推薦:OSGi入門與實踐全攻略
導入和導出服務套件
聯絡管理(Contact Management)應用程序包含兩個套件。第一個套件是 ContactDAO,與數據庫進行會話並將 ContactDAO 對象導出為OSGi服務。第二個套件是之前開發的 HelloWorld 應用程序,我們將其擴展,導入 ContactDAO 對象(即被導出的OSGi服務)。
下面讓我們先從創建 ContactDAO 套件開始。為了簡單易行,我們不會在套件中添加真實的數據庫互動邏輯;作為替代,每個方法僅將其方法名稱寫到 Eclipse 控制台。
首先創建 com.javaworld.sample.osgi.spring.contact.Contact.java 類,用來從 ontactDAO 將數據傳遞到 HelloWorld 套件。程序如代碼清單 3 所示。(Contact.Java 是一個簡單的類,表示數據庫中的一個聯絡記錄。)
代碼清單 3. Contact.Java
- package com.Javaworld.sample.osgi.spring.contact;
- public class Contact {
- int contactId;
- String firstName;
- String lastName;
- public int getContactId() {
- return contactId;
- }
- public void setContactId(int contactId) {
- this.contactId = contactId;
- }
- }
下一步,我們來創建 ContactDAO.Java 接口,程序如代碼清單 4 所示。
代碼清單 4. ContactDAO 接口
- package com.Javaworld.sample.osgi.spring.contact;
- public interface ContactDAO {
- public List getContactList();
- public Contact getContact(int contactId);
- public void insertContact(Contact contact);
- public void updateContact(Contact contact);
- public void deleteContact(int contactId);
- }
ContactDAO 是一個簡單的 CRUD 接口:它定義了創建、更新、檢索以及刪除操作的方法。
現在,創建 ContactDAO.Java 類的實現,程序如代碼清單 5 所示。
代碼清單 5. ContactDAOImpl.Java
- package com.Javaworld.sample.osgi.spring.contact.impl;
- public class ContactDAOImpl implements ContactDAO {
- public Contact getContact(int contactId) {
- System.out.println("Inside ContactDAOImpl.getContact()");
- return null;
- }
- // Do nothing implementation of all other methods defined in ContactDAO
- }
ContactDAOImpl.Java 為 ContactDAO 接口提供了一個“do nothing”(返回空)的實現。我們所要做的是利用這個類將方法名稱寫入到 System.Out。
請注意 Contact 和 ContactDAO 都必須是公共類(為了使用 ContactDAO 服務,其他套件需要訪問它們),並且位於 com.javaworld.sample.osgi.spring.contact 包之中。但是,實際的實現類 ContactDAOImpl.java(對於 ContactDAO 套件是一個內部類)位於 com.Javaworld.sample.osgi.spring.contact.impl 包中。
下面,我們來修改 ContactDAO 套件的 MANIFEST.MF 文件,以導出 com.javaworld.sample.osgi.spring.contact 套件,這樣就可以從 HelloWorld 套件訪問它了。我們只需在 MANIFEST.MF 中添加一行代碼:Export-Package: com.Javaworld.sample.osgi.spring.contact
Spring DM的 Spring 配置
下面,我們將創建 Spring 配置文件。Spring DM中推薦的方法是將配置劃分為兩個文件,一個用於定義 Spring bean,另一個用於將 Spring 輸出為 OSGi 服務。下面,我們也會將作為示例的應用程序的配置劃分為兩個文件。第一步是在 META-INF/spring 文件夾中創建一個 contactdao-service.XML 文件,程序如代碼清單 6 所示。
代碼清單 6. Spring 語境(contex)文件
- < ?XML version="1.0" encoding="UTF-8"?>
- < beans XMLns="http://www.springframework.org/schema/beans"
- XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- < bean name="contactDAOService"
- class="com.Javaworld.sample.osgi.spring.contact.impl.ContactDAOImpl">
- < /bean>
- < /beans>
這個簡單的 Spring 語境文件定義了 contactDAOService,指向 com.Javaworld.sample.osgi.spring.contact.impl.ContactDAOImpl 類。
下一步,我們將創建 META-INF/spring/contactdao-osgi.XML 文件,用於將 contactDAOService 對象導出為 OSGi 對象:
代碼清單 7. contactdao-osgi.XML
- < ?XML version="1.0" encoding="UTF-8"?>
- < beans XMLns="http://www.springframework.org/schema/beans"
- XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- XMLns:osgi="http://www.springframework.org/schema/osgi"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
- < osgi:service id="contactDAOOSGiService" ref="contactDAOService"
- interface="com.Javaworld.sample.osgi.spring.contact.ContactDAO">
- < /osgi:service>
- < /beans>
contactdao-osgi.XML 僅包含一個 < service> 元素,用於將 Spring bean 導出為公共寄存器裡的 OSGi 服務。服務 < service>[元素]必須最少具有兩個屬性:一個是 id 屬性,包含一個與導出 Spring bean 的名稱相等的值,另一個是 interface 屬性,它的值應與該接口名稱相等(該接口名稱下的服務將會被導出)。(< service>元素所支持屬性的完整列表,請參閱 Spring DM參考指南)。
現在我們的 ContactDAO 已經准備好了。下一步是對 HelloWorld 進行擴展,這樣它就可以使用新的服務了。
作為消費者的 HelloWorld
如果想要這個簡單的 HelloWorld 應用程序能夠擔任消費者的角色,我們必須賦予它這樣做的權限。第一步是更改該套件的 MANIFEST.MF 文件,添加一個 Import-Package 語句,如下所示:
- Import-Package: com.Javaworld.sample.osgi.spring.contact
現在,HelloWorld 套件將能夠訪問從 ContactDAO 套件的 com.Javaworld.sample.osgi.spring.contact package 導出的類。
下面我們將修改 HelloWorld.Java 類,如代碼清單 8 所示。
代碼清單 8. HelloWorld.Java 的更改
- public class HelloWorld {
- ContactDAO contactDAO;
- public ContactDAO getContactDAO() {
- return contactDAO;
- }
- public void setContactDAO(ContactDAO contactDAO) {
- this.contactDAO = contactDAO;
- }
- public void start() throws Exception {
- System.out.println("Hello Spring World!! " );
- System.out.println(contactDAO.getContactList() );
- }
- public void stop() throws Exception {
- System.out.println("Goodbye Spring World!!");
- }
- }
在代碼清單8 中,我們首先將 ContactDAO 作為 Java bean 屬性添加進來,包含所有相關的 getter 和 setter 方法。接著,我們修改類的 start() 方法,來調用 ContactDAO 服務的 getContactList() 方法,以及輸出“Hello Spring World!!”消息。
Spring 配置文件
HelloWorld 套件的 Spring 配置文件分為兩個文件:helloworld.xml 和 helloworld-osgi.xml。我們先從 helloworld-osgi.XML 開始,該文件如代碼清單 9 所示。
代碼清單 9. Spring 配置- helloworld-osgi-XML
- < ?XML version="1.0" encoding="UTF-8"?>
- < beans XMLns="http://www.springframework.org/schema/beans"
- XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- XMLns:osgi="http://www.springframework.org/schema/osgi"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
- < osgi:reference id="contactDAOService" interface="com.Javaworld.sample.osgi.spring.contact.ContactDAO"/>
- < /beans>
這個 helloworld-osgi.XML 文件聲明了一個引用元素,該元素用於索引 OSGi 服務並將其作為 Spring bean 在 HelloWorld 套件中可用。之前已經提到,引用元素包含兩個屬性:id 和interface。在將 OSGi 服務添加為應用程序中的 Spring bean 時,Spring DM將使用 id 屬性的值。對於這種情況,我們已經指出,Spring DM應使該服務作為 contactDAOService 在 HelloWorld 套件的應用程序語境中可用。
第二個屬性是 interface。Spring DM將使用該屬性的值來查找與指定接口匹配的服務。在示例代碼中,我們已說過,我們想要一個實現 com.Javaworld.sample.osgi.spring.contact.ContactDAO 接口的服務。
Spring DM調用 BundleContext.getServiceReference() 查找實現了 com.Javaworld.sample.osgi.spring.contact.ContactDAO 接口的服務。如果在 OSGi 框架中,與需要相匹配的服務多於一個,那麼將返回具有最高等級的那個服務。此外,你還可以使用 filter 屬性來精確地定義你想要的服務。
下一步,我們將修改 helloworld.XML 文件,使它能夠將 contactDAOService 對象注入到我們的 hello bean 中,如代碼清單 10 所示。
代碼清單 10. Spring 配置 - helloworld.XML
- < ?XML version="1.0" encoding="UTF-8"?>
- < beans XMLns="http://www.springframework.org/schema/beans"
- XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- < bean name="hello" class="com.Javaworld.osgi.spring.HelloWorld"
- init-method="start" destroy-method="stop" >
- < property name="contactDAO" ref="contactDAOService"/>
- < /bean>
- < /beans>
一旦將 ContactDAOService 注入到套件的應用程序語境中,你就能夠使用它作為任何你想要的其他 Spring bean。在示例代碼中,我們將該服務作為一個 HelloWorld bean 的contactDAO 屬性進行注入。
HelloWorld 導入服務
在 Eclipse IDE 中執行你的套件,當你啟動 HelloWorld 套件時,在你的控制台裡應顯示“Hello Spring World!! Inside ContactDAOImpl.getContactList()”消息。在後台,一旦 Spring extender 套件被啟動,它將看到存在兩個 Spring 提供的套件。作為響應,它將首先為 ContactDAO 套件創建一個應用程序語境。同時,它查找 contactdao-osgi.XML 文件並將 ContactDAO 作為公共寄存器中的 OSGi 服務進行導出。接著,它將試圖為 HelloWorld 套件創建一個應用程序語境。看到它具有一個引用元素,extender 調用 BundleContext.getService("com.javaworld.sample.osgi.spring.contact.ContactDAO") 方法,目的在於查找實現 com.Javaworld.sample.osgi.spring.contact.ContactDAO 接口的類服務。
在示例代碼(見代碼清單 5)中,ContactDAOImpl 是唯一實現了該接口的服務,因此 extender 將返回 ContactDAOImpl 的一個對象。一旦該對象被返回,Spring DM就會將其作為 contactDAO 屬性 注入到 HelloWorld bean 中。