`
tubaluer
  • 浏览: 1443983 次
文章分类
社区版块
存档分类
最新评论
  • sblig: c / c++ 是不一样的都会输出 100
    j = j++

在OSGi容器外和OSGi进行交互

 
阅读更多

来源:http://www.blogjava.net/BlueDavy/archive/2009/04/24/267425.html

在使用OSGi时,有些时候会需要在OSGi容器外获取OSGi服务,加载OSGi容器加载的class,或者说需要内嵌OSGi容器,本篇blog以一个简单的例子来说明如何基于equinox实现OSGi容器的内嵌,或者说通过程序来启动equinox,同时也通过此例子展示下如何在容器外来获取OSGi服务以及加载OSGi容器里面其他插件的class,同时还会附送一个如何让OSGi容器里的插件能加载到OSGi容器外的类的方法。

对于用过equinox的同学,或者看过我之前那两篇OSGi opendoc附带的例子的同学而言,都会知道通过命令行来启动equinox的方式,常见的一种脚本为:java -jar plugins/org.eclipse.osgi_3.2.1.R32x_v20060919.jar -configuration configuration -console,然后在当前目录的configuration目录下放置一个config.ini,在此config.ini中通过osgi.bundles=来配置需要加载和启动的插件,例如osgi.bundles=a.jar@start,那么要在程序中启动equinox容器,其实基本是差不多的。

查看equinox的代码,会看到调用上面的org.eclipse.osgi.jar后执行的是EclipeStarter中的静态run方法,因此只需在外部传入合适的参数,并调用此run方法即可完成equinox的启动,在程序中启动equinox,通常希望做到的是能够指定config.ini的配置信息以及插件的位置,而不是由equinox去决定,如果不进行设置,默认情况下EclipseStarter将会在工作路径下产生configuration,并以该configuration目录下的config.ini作为equinox启动的配置,对于osgi.bundles配置的bundle的路径,默认则为当前EclipseStarter代码所在的目录,例如上面的命令行,equinox在启动时就会从plugins目录中去加载插件,这通常是无法满足在程序中启动equinox的需求的,如果想自定义equinox启动的配置信息,而不是通过去加载指定的configuration中的config.ini,那么可以在程序中调用FrameworkProperties.setProperty来设置启动equinox的配置信息,如希望指定osgi.bundles中指定的加载的bundle的相对路径,那么可以在equinox启动的配置信息中增加osgi.syspath的指定,FrameworkProperties.setProperty("osgi.syspath",你希望指定的bundle所在的路径),equinox启动的配置信息还有很多种,具体有需要的话可以查看EclipseStarter中processCommandLine的方法,通过这样的方式后,就可以采用类似这样的方式来启动equinox:EclipseStarter.run(new String[]{"-console"},null);按照上面这样的方式就可以实现在外部程序中启动equinox了。

OSGi通过BundleContext来获取OSGi服务,因此想在OSGi容器外获取OSGi服务,首要的问题就是要先在OSGi容器外获取到BundleContext,EclipseStarter中提供了一个getSystemBundleContext的方法,通过这个方法可以轻松的拿到BundleContext,而通过BundleContext则可以容易的拿到OSGi服务的实例,不过这个时候要注意的是,如果想执行这个OSGi服务实例的方法的话,还是不太好做的,因为容器外的classloader和OSGi服务实例的class所在的classloader并不相同,因此不太好按照java对象的方式直接去调用,更靠谱的是通过反射去调用。

如果想在容器外获取到OSGi容器里插件的class,一个可选的做法是通过BundleContext获取到Bundle,然后通过Bundle来加载class,采用这样的方法加载的class就可以保证其是相同的,否则会出现容器外的一个A.class会不等于容器里插件的A.class,这个原因对于稍微知道java classloader机制的人都理解的。

按照上面的说法,一个简单的启动Equinox以及与OSGi容器交互的类可以这么写:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> /**
*启动并运行equinox容器
*/
publicstaticvoidstart()throwsException{
//根据需要加载的bundle组装出类似a.jar@start,b.jar@3:start这样格式的osgibundles字符串来
StringosgiBundles="";
//配置Equinox的启动
FrameworkProperties.setProperty("osgi.noShutdown","true");
FrameworkProperties.setProperty(
"eclipse.ignoreApp","true");
FrameworkProperties.setProperty(
"osgi.bundles.defaultStartLevel","4");
FrameworkProperties.setProperty(
"osgi.bundles",osgiBundlesBuilder.toString());
//根据需要设置bundle所在的路径
StringbundlePath="";
//指定需要加载的plugins所在的目录
FrameworkProperties.setProperty("osgi.syspath",bundlePath);
//调用EclipseStarter,完成容器的启动,指定configuration目录
EclipseStarter.run(newString[]{"-configuration","configuration","-console"},null);
//通过EclipeStarter获取到BundleContext
context=EclipseStarter.getSystemBundleContext();
}

/**
*停止equinox容器
*/
publicstaticvoidstop(){
try{
EclipseStarter.shutdown();
context
=null;
}
catch(Exceptione){
System.err.println(
"停止equinox容器时出现错误:"+e);
e.printStackTrace();
}
}

/**
*从equinox容器中获取OSGi服务instance还可以基于此进一步处理多服务接口实现的状况
*
*
@paramserviceName服务名称(完整接口类名)
*
*
@returnObject当找不到对应的服务时返回null
*/
publicstaticObjectgetOSGiService(StringserviceName){
ServiceReferenceserviceRef
=context.getServiceReference(serviceName);
if(serviceRef==null)
returnnull;
returncontext.getService(serviceRef);
}

/**
*获取OSGi容器中插件的类
*/
publicstaticClass<?>getBundleClass(StringbundleName,StringclassName)throwsException{
Bundle[]bundles
=context.getBundles();
for(inti=0;i<bundles.length;i++){
if(bundleName.equalsIgnoreCase(bundles[i].getSymbolicName())){
returnbundles[i].loadClass(className);
}
}
}

在实现了OSGi容器外与OSGi交互之后,通常会同时产生一个需求,就是在OSGi容器内的插件要加载OSGi容器外的类,例如OSGi容器内提供了一个mvc框架,而Action类则在OSGi容器外由其他的容器负责加载,那么这个时候就会产生这个需求了,为了做到这点,有一个比较简单的解决方法,就是编写一个Bundle,在该Bundle中放置一个允许设置外部ClassLoader的OSGi服务,例如:
public class ClassLoaderService{

public void setClassLoader(ClassLoader classloader);

}
然后基于上面的方法,在外部启动equinox的类中去反射执行ClassLoaderService这个OSGi服务的setClassLoader方法,将外部的classloader设置进来,然后在OSGi容器的插件中需要加载OSGi容器外的类的时候就调用下这个ClassLoaderService去完成类的加载。

基于以上说的这些方法,基本上是可以较好的实现OSGi容器与其他容器的结合,例如在tomcat中启动OSGi等,不过在动态化这块就没有那么好处理了,除非外部的容器也能提供相应的动态的机制,具体在下一篇的blog中再来细致的讨论下OSGi的动态化。
分享到:
评论

相关推荐

    jbehave-osgi:https的只读镜像

    在任何使用 Felix GoGo 命令的 OSGi 容器内交互; 它由以下组件组成: jbehave-osgi-bundles/org.jbehave.osgi.core。 包装 JBehave 核心 API 并公开其功能的包; 这是所有情况下的必需捆绑包。 jbehave-osgi-...

    ClassLoader类加载机制

    现在类加载器在 Web 容器和 OSGi 中得到了广泛的使用。一般来说,Java 应用的开发人员不需要直接同类加载器进行交互。Java 虚拟机默认的行为就已经足够满足大多数情况的需求了。不过如果遇到了需要与类加载器进行...

    java类加载器实例

    现在类加载器在 Web 容器和 OSGi 中得到了广泛的使用。一般来说,Java 应用的开发人员不需要直接同类加载器进行交互。Java 虚拟机默认的行为就已经足够满足大多数情况的需求了。不过如果遇到了需要与类加载器进行...

    camel-jbpm:骆驼JBPM组件

    还有OSGI功能,可将组件部署在OSGI容器上,例如Fuse 6.2 该组件支持以下操作 流程操作: START_PROCESS,ABORT_PROCESS_INSTANCE,SIGNAL_EVENT,GET_PROCESS_INSTANCE,GET_PROCESS_INSTANCES 规则运算: FIRE_...

    java开源包1

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包11

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包2

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包3

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包6

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包5

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包10

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包4

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包8

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包7

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包9

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包101

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    Java资源包01

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    JAVA上百实例源码以及开源项目

     在对象创建的过程中将被容器调用,onMessage函数方法接收消息参数,将其强制转型为合适的消息类型,同时打印出消息的内容。同时一个mail note将被发送给消息发送者,发送一个e-mail通知给由recipient参数确定的e-...

    JAVA上百实例源码以及开源项目源代码

     在对象创建的过程中将被容器调用,onMessage函数方法接收消息参数,将其强制转型为合适的消息类型,同时打印出消息的内容。同时一个mail note将被发送给消息发送者,发送一个e-mail通知给由recipient参数确定的e-...

Global site tag (gtag.js) - Google Analytics