某篇Blog看到的,在SpringDM + Equninox 中, 除了在Console 裡執行INSTALL,UPDATE,UNINSTALL,REFRESH,
4個指令可以達到針對Bundle的處理,相關在SpringDM的設定也有一些能達到。
如果要update一個class,我們可以考慮Update整個bundle, 更新可以用update該bundle(在MANIFEST.MF中增加Bundle-UpdateLocation來指定Bundle更新時所使用的文件),或著是unsintall舊的,再install新的。
Equinox中,當update一個Bundle時,如果這個Bundle中有Export package,此Bundle是singleton模式的話,在update後仍然保留了同樣的Bundle SymbolicName,是無法update成功的,會報出一個已經有相同的Singleton的Bundle存在的錯誤,因此update這種方法僅適用於沒有對外Export package的bundle,如bundle沒有對外Export package,Equinox則可正常的完成update過程。這又跟OSGi對於Install Update...等行為的classLoader有關。
OSGi實現hot deployment時,要合理的規劃系統,比較好的方法如:
1: Interface & implements 分開
2: 盡量使用OSGi Service的方法, 而不是直接使用其Class方式
實際上在SpringDM(On Eclipse Virgo)上有一些方法可達到差不多的效果
我們有一個Bundle 內含一個Interface ,
com.xyz.MessageService
用Spring DM 註冊一個OSGi Service時會這樣寫
<beans:bean id="beanToPublish" class="com.xyz.imp.MessageServiceImp"/> <service ref="beanToPublish" interface="com.xyz.MessageService"/>這時就會將一個OSGi Service register,
com.xyz.MessageService會publish 到osgi service上
如果有另一個Service定義如下
<beans:bean id="beanToPublish2" class="com.xyz.imp.MessageServiceImp2"/> <service ref="beanToPublish2" interface="com.xyz.MessageService"/>
這時候如果有一個bundle reference 到這個osgi service 的interface 時會如何?
(如果這邊的2個Service 的interface 是自帶在自己的Bundle裡面的話,會被認為不同的Service)
<osgi:reference id="beanToReference" interface="com.xyz.MessageService"/>
這時會導入較早被啟動的bundle , OSGi在bundle 啟動時會給予一個ID值,愈早的值愈小。
如果我們要達成hot deploye 的方法, 在SpringDm裡面有一些方法能用
1: Service Ranking
使用OSGi Service下的 Ranking Attribute 時, rank 高的會被reference(相同interface impl的bundle) , 此時原本reference的bundle不需要再refresh or update , 直接hot deployed
<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface" ranking="9"/>
2: Bundle Object
在Spring Dm裡面使用osgi:bundle,可以建立一個bundle object, action設成Update,在Bundle被deploy時會觸發update的動作
<osgi:bundle id="aBundle" symbolic-name="OSGiWebApp.validateXML" action="update"/>
沒有留言:
張貼留言