從package依賴和服務(wù)依賴兩個(gè)角度來看,假設(shè)A Bundle對外提供了HotDeployDemoService實(shí)現(xiàn),此實(shí)現(xiàn)依賴了B Bundle對外export的org.osgichina.domain的package以及D Bundle對外export的org.osgichina.hotdeploy.service的package,實(shí)現(xiàn)還需要調(diào)用DBService,此OSGi
Service由C Bundle對外提供,C Bundle也依賴于D Bundle export的DBService的接口package,同時(shí)此實(shí)現(xiàn)采用了一個(gè)計(jì)數(shù)器來計(jì)數(shù)執(zhí)行的次數(shù),代碼片段如下:
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秒鐘執(zhí)行下DemoService的execute方法,啟動完畢后,首先安裝上A Bundle,此時(shí)由于A Bundle缺少了所依賴的package以及OSGi服務(wù),其需要對外提供的OSGi服務(wù)必然也無法激活,因此console輸出了以下信息:
未找到需要調(diào)用的服務(wù)
安裝并啟動B Bundle和DBundle,嘗試啟動A Bundle,Console仍然輸出:
未找到需要調(diào)用的服務(wù)
繼續(xù)安裝并啟動C
Bundle,嘗試啟動A Bundle,Console輸出:
execute times:1
execute DBComponent,username is:bluedavy
從上可見,在Felix中要達(dá)到即插即用的效果還是非常容易的,只要安裝并啟動了所依賴的package(BBundle、DBundle)和OSGi服務(wù)所在的Bundle(CBundle)后,再行啟動依賴這些package和OSGi 服務(wù)的Bundle(ABundle),那么新安裝的Bundle的功能就可被使用,效果也稱得上是即插即用了。
l 熱部署
熱部署期待的效果是直接覆蓋需要更新的jar,所有新的請求都會自動執(zhí)行到新的代碼中,且保留更新的對象的狀態(tài)。
仍然采用即插即用中的例子,分別來看看當(dāng)B Bundle和C Bundle更新時(shí)A Bundle服務(wù)執(zhí)行的狀況,將B Bundle的getName修改為return “osgi”;,覆蓋B Bundle,執(zhí)行update后,觀察console的輸出:
execute times:23
execute DBComponent,username is:bluedavy
從此可見,update后B Bundle的修改并沒生效,嘗試執(zhí)行下refresh后,繼續(xù)觀察console的輸出:
execute times:1
execute DBComponent,username is:osgi
可以看到,此時(shí)B
Bundle的修改已生效,但伴隨的是execute times這個(gè)對象狀態(tài)的重置。
繼續(xù)修改C Bundle,將C Bundle打印的信息改為,execute
new DBComponent,修改完畢后覆蓋C Bundle,執(zhí)行update后,觀察console的輸出:
execute times:1
execute new DBComponent,username is:osgi
可見C Bundle的修改立刻生效了,但同樣伴隨著的是execute times這個(gè)對象狀態(tài)的重置。
按照如上的試驗(yàn),在使用Felix的情況下,如要更新其他Bundle依賴的package的Bundle,需要采用的步驟為:覆蓋bundle文件àupdate
bundleàrefresh,;如要更新其他Bundle需要調(diào)用的OSGi服務(wù)的Bundle,需要采用的步驟為:覆蓋bundle文件àupdate bundle;但兩者伴隨著的都是更新的Bundle以及依賴(遞歸)了其的Bundle中的對象狀態(tài)的丟失,可見,要想基于Felix就直接得到熱部署的效果還是做不到的,需要在Felix的基礎(chǔ)上自行做一定的擴(kuò)展。
l 即刪即無
即刪即無期望的效果是在停止Bundle后,其所對外export的package以及OSGi Service都不再可用,仍然采用即插即用中的例子進(jìn)行測試。
首先來看看停止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了,繼續(xù)觀察console的輸出:
未找到需要調(diào)用的服務(wù)
恩,這才是期待的效果,說明此方法可行。
繼續(xù)安裝上B Bundle,來看下停止C
Bundle后,console的輸出:
未找到需要調(diào)用的服務(wù)
恩,正如期待的效果,說明此方法可行。
由上可以看出,在Felix中要達(dá)到即刪即無的效果,對于有對外export package的Bundle,在uninstall后必須再執(zhí)行refresh動作;而對于有對外提供OSGi服務(wù)的Bundle,則只需執(zhí)行stop動作即可。