Felix動態化的試驗
在動態化方面,最為關心的是Felix在“即插即用”、“熱部署”以及“即刪即無”三點上的表現,這三點涉及到的主要是引用對象的遷移以及對象狀態的保留,而對于OSGi的應用,引用對象的遷移涉及到的為package依賴以及OSGi服務依賴的遷移,在對象狀態的保留上,OSGi不提供支持,為了更方便的觀察Felix在動態化的表現,在程序中直接啟動Felix,通過這樣的方式獲取到BundleContext,進而調用Bundle中OSGi服務的方法來檢測package依賴、OSGi服務依賴在“即插即用” 、“熱部署”以及“即刪即無”這三種情況下的變化情況,在程序中啟動Felix的代碼片段如下:
FrameworkFactory factory=new FrameworkFactory();
Properties startProps=new Properties();
startProps.put("felix.auto.start.1", "file:bundle/org.apache.felix.scr-1.0.8.jar
file:bundle/org.apache.felix.shell-1.2.0.jar
file:bundle/org.apache.felix.shell.tui-1.2.0.jar
file:bundle/org.apache.felix.bundlerepository-1.4.0.jar");
List list = new ArrayList();
list.add(new AutoActivator(startProps));
startProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
startProps.put("felix.log.level", "1");
startProps.put("osgi.shell.telnet", "on");
Framework framework=factory.newFramework(startProps);
framework.start();
context=framework.getBundleContext();
l 即插即用
即插即用是硬件體系中宣傳的最多的一項,例如USB硬件等,對于OSGi的應用,此時期待的是安裝上新的Bundle后,此新Bundle的功能即可正常使用。
從package依賴和服務依賴兩個角度來看,假設A Bundle對外提供了HotDeployDemoService實現,此實現依賴了B Bundle對外export的org.osgichina.domain的package以及D Bundle對外export的org.osgichina.hotdeploy.service的package,實現還需要調用DBService,此OSGi
Service由C Bundle對外提供,C Bundle也依賴于D Bundle export的DBService的接口package,同時此實現采用了一個計數器來計數執行的次數,代碼片段如下: A Bundle public class DemoComponent implements DemoService { private AtomicInteger count=new AtomicInteger(0); private DBService dbservice; public void setDBService(DBService dbservice){ this.dbservice=dbservice; } public void unsetDBService(DBService dbservice){ if(this.dbservice==dbservice){ this.dbservice=null; } } /* (non-Javadoc) * @see
org.osgichina.hotdeploy.demo.service.DemoService#execute() */ @Override public void execute() { System.out.println("execute times:"+(count.incrementAndGet())); User user=new User(); dbservice.execute(user.getName()); } } B Bundle public class User { public String getName(){ return "bluedavy"; } } C Bundle public class DBComponent implements DBService { @Override public void execute(String username) { System.out.println("execute
DBComponent,username is:"+username); } } 通過程序在外部啟動Felix,每5秒鐘執行下DemoService的execute方法,啟動完畢后,首先安裝上A Bundle,此時由于A Bundle缺少了所依賴的package以及OSGi服務,其需要對外提供的OSGi服務必然也無法激活,因此console輸出了以下信息: 未找到需要調用的服務 安裝并啟動B Bundle和DBundle,嘗試啟動A Bundle,Console仍然輸出: 未找到需要調用的服務 繼續安裝并啟動C
Bundle,嘗試啟動A Bundle,Console輸出: execute times:1 execute DBComponent,username is:bluedavy 從上可見,在Felix中要達到即插即用的效果還是非常容易的,只要安裝并啟動了所依賴的package(BBundle、DBundle)和OSGi服務所在的Bundle(CBundle)后,再行啟動依賴這些package和OSGi 服務的Bundle(ABundle),那么新安裝的Bundle的功能就可被使用,效果也稱得上是即插即用了。 l 熱部署 熱部署期待的效果是直接覆蓋需要更新的jar,所有新的請求都會自動執行到新的代碼中,且保留更新的對象的狀態。 仍然采用即插即用中的例子,分別來看看當B Bundle和C Bundle更新時A Bundle服務執行的狀況,將B Bundle的getName修改為return “osgi”;,覆蓋B Bundle,執行update后,觀察console的輸出: execute times:23 execute DBComponent,username is:bluedavy 從此可見,update后B Bundle的修改并沒生效,嘗試執行下refresh后,繼續觀察console的輸出: execute times:1 execute DBComponent,username is:osgi 可以看到,此時B
Bundle的修改已生效,但伴隨的是execute times這個對象狀態的重置。 繼續修改C Bundle,將C Bundle打印的信息改為,execute
new DBComponent,修改完畢后覆蓋C Bundle,執行update后,觀察console的輸出: execute times:1 execute new DBComponent,username is:osgi 可見C Bundle的修改立刻生效了,但同樣伴隨著的是execute times這個對象狀態的重置。 按照如上的試驗,在使用Felix的情況下,如要更新其他Bundle依賴的package的Bundle,需要采用的步驟為:覆蓋bundle文件àupdate
bundleàrefresh,;如要更新其他Bundle需要調用的OSGi服務的Bundle,需要采用的步驟為:覆蓋bundle文件àupdate bundle;但兩者伴隨著的都是更新的Bundle以及依賴(遞歸)了其的Bundle中的對象狀態的丟失,可見,要想基于Felix就直接得到熱部署的效果還是做不到的,需要在Felix的基礎上自行做一定的擴展。 l 即刪即無 即刪即無期望的效果是在停止Bundle后,其所對外export的package以及OSGi Service都不再可用,仍然采用即插即用中的例子進行測試。 首先來看看停止B
Bundle后,觀察console的輸出: execute times:168 execute new DBComponent,username is:osgi 可見,這么做并不會影響A
Bundle使用B Bundle export的package,那么嘗試使用uninstall B Bundle,這下行了吧,滿心期待的觀察console的輸出: execute times:185 execute new DBComponent,username is:osgi 居然仍然可以使用,看來只能再嘗試下refresh了,繼續觀察console的輸出: 未找到需要調用的服務 恩,這才是期待的效果,說明此方法可行。 繼續安裝上B Bundle,來看下停止C
Bundle后,console的輸出: 未找到需要調用的服務 恩,正如期待的效果,說明此方法可行。
posted on 2009-05-25 22:58 BlueDavy 閱讀(5348) 評論(4) 編輯 收藏 所屬分類: OSGi、SOA、SCA