===== 作用 ===== - 应用内模块的隔离 - 一个模块一个服务,一个服务的变更不影响其他服务(主要是二方库依赖) ===== 隔离原理 ===== bundle间之所以能隔离,因为每个bundle都有一个单的ClassLoader,且该ClassLoader的 parent ClassLoader为空(也就是说不会委派给其他ClassLoader)。但是每个bundle加载Import-Package时,会使用Export-Package的ClassLoader去加载。这也就保证了不同bundle间也可以共享类 ===== 运行方式 ===== - all bundle模式:所有逻辑都以bundle的方式存在 - embedded 模式:在主应用中启动一个osgi框架 + 其他bundle 本文主要讲解embedded 模式 的使用 ===== bundle间的调用 ===== bundle间服务调用的方式 (主程序也是作为一个bundle来工作的) ==== 通过反射调用 ==== - bundle-service注册服务,bundle-cliet获取服务 - 根据方法名,反射调用方法 优点 * 简单无依赖 ==== 通过共享接口调用 ==== * bundle-client bundle-server之间依赖同一个二方库(二方库中定义了服务的接口),bundle-server实现服务,bundle-client调用服务 缺点: * 实现复杂 - 接口要单独一二方库,被2个bundle依赖 (bundle-client mvn依赖的scope=provided) - 配置bundle-server 暴露package - 配置bundle-server 引入package ===== 样例代码 ===== === bundle mvn配置 === org.apache.felix org.apache.felix.framework 6.0.3 org.apache.felix maven-bundle-plugin true ${project.version} $(replace;${project.artifactId};-;_) aa.bb.cc.intf;version="${project.version}" org.osgi.framework aa.bb.cc.impl.App === bundle中注册服务 === public class App implements BundleActivator { private static BundleContext context; static BundleContext getContext() { return context; } @Override public void start(BundleContext bundleContext) throws Exception { System.out.println("start bundle -- " + bundleContext); App.context = bundleContext; Hashtable props = new Hashtable(); props.put("Language", "English"); context.registerService(IHello.class.getName(), new DefaultHelloServiceImpl(), props); } @Override public void stop(BundleContext bundleContext) throws Exception { App.context = null; System.out.println("end bundle"); } public class DefaultHelloServiceImpl implements IHello { @Override public String say() { return "Hello osgi,service"; } } } === 主程序中通过反射调用服务 === public static void main(String[] args) { try { final Map configMap = new HashMap(); configMap.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit"); Felix felix = new Felix(configMap); felix.init(); final BundleContext context = felix.getBundleContext(); // 加载一个bundle Bundle bundle = context.installBundle("file:/Users/fangqiang/Documents/osgibundle/server/target/server-1.0-SNAPSHOT.jar"); // 启动bundle bundle.start(); // 启动osgi框架 felix.start(); // 通过反的方法调用bundle中的服务 for (ServiceReference registeredService : bundle.getRegisteredServices()) { Object service = context.getService(registeredService); Method say = service.getClass().getMethod("say"); System.out.println(say.invoke(service)); } } catch (Exception ex) { System.exit(0); } } === 主程序中通过共享接口调用 === public static void main(String[] args) { try { final Map configMap = new HashMap(); configMap.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit"); // 程序中通过configMap配置要暴露的包 (如果是bundle中直接在pom.xml中的Export-Package中配置即可) configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "aa.bb.common.intf; version=1.0.0.SNAPSHOT"); HostActivator activator = new HostActivator(); // 将主程序中的服务注册到osgi中 (如果没有服务要暴露给bundle,则不需要该配置) configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, Arrays.asList(activator)); Felix felix = new Felix(configMap); felix.init(); BundleContext context = felix.getBundleContext(); // 加载一个bundle Bundle bundle = context.installBundle("file:/Users/fangqiang/Documents/osgibundle/server/target/server-1.0-SNAPSHOT.jar"); // 启动bundle bundle.start(); // 启动osgi框架 felix.start(); // 通过接口调用bundle中服 System.out.println(((IHello1)context.getService(context.getServiceReference(IHello1.class.getName()))).say()); } catch (Exception ex) { System.exit(0); } } === 其他bundle中通过共享接口调用 === public class App implements BundleActivator { @Override public void start(BundleContext ctx) { System.out.println("----------------hello client start---------------------"); ServiceReference ref = ctx.getServiceReference(IHello.class.getName()); IHello hello = (IHello) ctx.getService(ref); hello.say(); System.out.println("----------------hello client start---------------------"); } @Override public void stop(BundleContext ctx) throws Exception { } }