服務接口+版本+屬性注冊/查找機制
在使用Spring的時候,我們習慣于用bean的名稱作為注冊、查找的條件,這也就意味著bean的引用是唯一的了,而不能來查找、注入一系列具備相同功能但不同實現的bean,這種應用的場景其實還是很多的,尤其在擴展的場景中,在這篇blog中以一個應用場景來說明下這種需求,順便也宣傳下OSGi的服務接口+版本+屬性的注冊和查找機制。
以將Spring bean發布為DSF服務的bean來講,這個bean需要做到根據發布DSF服務的方式,調用相應的具體發布DSF服務的實現bean,同時要做到的自然是在以后增加了新的發布方式后,不需要修改這個bean的代碼。
要實現這個需求,首先想到的是這樣的解決方案:
1、在這個bean中直接注入所有的發布DSF服務實現的bean,在調用的時候可以根據規則尋找到相應的bean,這個在Spring中能夠實現的方式也許是這樣:
<bean id="DSFServiceExporterFactory" class="將Spring bean發布為DSF服務的bean">
<property name="exporterClassMap">
<map>
<entry key="jndi"><ref bean="以JNDI方式發布DSF服務端的bean"></entry>
<entry key="webservice"><ref bean="以Webservice方式發布DSF服務端的bean"></entry>
</map>
</property>
</bean>
2、第二種實現方法就很常見了,就是寫個properties文件,配置各種發布方式具體對應的實現類。
但這兩種方法都不夠的優雅,它們都有個共同的特點,就是需要去維護一個共同的配置的地方,想象中最好的解決方法是類似這樣的配置:
<bean id="DSFServiceExporterFactory" class="將Spring bean發布為DSF服務的bean">
<property name="exporterClasses">
<ref bean="cn.bluedavy.dsf.exporter.*">
</property>
</bean>
這樣就把所有的cn.bluedavy.dsf.exporter.開頭的bean都注入到exporterClasses里了,當然,在根據具體的協議查找實現類時,又得提供一種支持方法了,好,不再去自己瞎琢磨了,來看看如果是OSGi的服務模型的話,會怎么樣去實現這樣的東西:
在OSGi中每個對外提供的service都以接口來定義,在上面的場景中,很明顯,自然會出現的一個現象就是如果多個服務實現同樣的接口的話怎么去找到自己要的那個服務呢,OSGi中多數采用的方法是為這個服務加上一個屬性標識,在查找服務時就可以通過接口,再加上屬性標識來查找到想要的服務了,又或者可以只查找接口,獲取到所有實現這類接口的服務。
按照這樣的模型的話上面的場景就很容易實現了,寫個模擬的配置文件:
<osgi:reference id="exporterClasses" interface="cn.bluedavy.dsf.exporter.DSFExporter"/>
<bean id="DSFServiceExporterFactory" class="將Spring bean發布為DSF服務的bean">
<property name="exporterClasses">
<ref bean="exporterClasses">
</property>
</bean>
這個和真實的會有些不同,但意思是差不多的,:),而OSGi的服務呢,在注入后可以直接通過ServiceReference這個對象來獲取到這個服務的相關屬性信息,這樣其實也就可以做到類似之前第一個解決方案的效果,但同時又解決了不需要維護統一文件的問題。
服務模型的這種語義性質的機制使得服務的概念表達得更為清楚,使用得也更為方便了,以接口來表達服務的功能是一種非常合理的方式,同時輔以屬性來描述實現此功能的方式(有點像元數據里的keyword)無疑更加全面的表達了此服務, 也使得使用者能夠更合理的選擇需要的服務實現。
版本機制在這篇blog中沒有提及,這個我想在實際的過程中大家應該都深受版本混淆的痛苦了,:),在這里不多描述了,服務模型目的無疑就是為了更加清晰的表達一個功能,并且讓使用者更加方便的查找、使用所需要的功能。
posted on 2008-02-13 18:00 BlueDavy 閱讀(3584) 評論(1) 編輯 收藏 所屬分類: OSGi、SOA、SCA