bundle间之所以能隔离,因为每个bundle都有一个单的ClassLoader,且该ClassLoader的 parent ClassLoader为空(也就是说不会委派给其他ClassLoader)。但是每个bundle加载Import-Package时,会使用Export-Package的ClassLoader去加载。这也就保证了不同bundle间也可以共享类
本文主要讲解embedded 模式 的使用
bundle间服务调用的方式 (主程序也是作为一个bundle来工作的)
优点
缺点:
<dependencies> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.framework</artifactId> <version>6.0.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <!--<version>2.4.0</version>--> <extensions>true</extensions> <configuration> <instructions> <Bundle-Version>${project.version}</Bundle-Version> <Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName> <!--要暴露的包--> <Export-Package> aa.bb.cc.intf;version="${project.version}" </Export-Package> <!--要引入的包--> <Import-Package> org.osgi.framework </Import-Package> <Bundle-Activator> aa.bb.cc.impl.App </Bundle-Activator> </instructions> </configuration> </plugin> </plugins> </build>
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<String, String> props = new Hashtable<String, String>(); 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); } }
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 { } }