从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的输出:
未找到需要调用的服务
恩,正如期待的效果,说明此方法可行。
由上可以看出,在Felix中要达到即删即无的效果,对于有对外export package的Bundle,在uninstall后必须再执行refresh动作;而对于有对外提供OSGi服务的Bundle,则只需执行stop动作即可。