简体   繁体   English

嵌入式OSGi:访问动态加载的包组件

[英]Embedded OSGi: accessing dynamically loaded bundle components

I'm getting a little lost when dealing with embedding OSGi into an application/library, loading a bundle at runtime and then using that bundle in the host application/library. 在将OSGi嵌入到应用程序/库中,在运行时加载捆绑软件然后在主机应用程序/库中使用该捆绑软件时,我有些迷惑。

This is code to load the bundle from my host: 这是从我的主机加载捆绑软件的代码:

// framework is the embedded OSGi framework
Bundle b = framework.getBundleContext().installBundle( "file:/project_dir/bundle/MyBundle.jar" );
b.start();

And the bundle consists of something really simple: 捆绑包含非常简单的内容:

public class Activator implements BundleActivator
{
  @Override
  public void start( BundleContext context )
  {
  }

  @Override
  public void stop( BundleContext context )
  {
  }

  public String shout()
  {
    return "let it all out";
  }
}

How would I access the shout() method from the host application? 如何从主机应用程序访问shout()方法?

In short: 简而言之:

  • Register your objects as OSGi services 将对象注册为OSGi服务
  • Get the OSGi services in the application/library that started the embedded OSGi container 在启动嵌入式OSGi容器的应用程序/库中获取OSGi服务

More detailed solution: 更详细的解决方案:

  • Define an interface in a separate jar that contains the shout() function 在包含shout()函数的单独jar中定义一个接口
  • Place the jar file on the classpath of the application/library 将jar文件放在应用程序/库的类路径中
  • Implement the interface in the Activator class of your bundle 在包的Activator类中实现接口
  • Register the instance of the Activator class as an OSGi service based on the interface 根据接口将Activator类的实例注册为OSGi服务
  • In the application/library, get the OSGi service based on the interface 在应用程序/库中,基于接口获取OSGi服务

Alternatively, if you do not have the interface in the application/library, you can still get the OSGi service and call the function using reflection. 或者,如果您在应用程序/库中没有该接口,则仍然可以获取OSGi服务并使用反射调用该函数。

Here are some details about the code to use following the previous answer: 以下是有关在先前答案之后使用的代码的一些详细信息:

  • The interface containing your method. 包含您的方法的接口。

     public interface MyInterface { String shout(); } 

    You can notice that it's a good approach to have two bundles for your library: one for the interface, and another for the implementation. 您可能会注意到,为库提供两个捆绑是一个好方法:一个捆绑用于接口,另一个捆绑用于实现。 It will prevent from having "refresh packages" issues when the implementation bundle went and come again. 当实现包再次出现时,它将防止出现“刷新包”问题。

  • The implementation of the previous interface: 上一个接口的实现:

     public class MyImpl implements MyInterface { public String shout() { return "let it all out"; } } 

    The package of the implementation doesn't need to be exported by the bundle. 该实现的包不需要通过捆绑包导出。 The class MyImpl won't be use directly by service consumers. 服务使用者不会直接使用MyImpl类。

  • The new code of the activator: 激活器的新代码:

     public class Activator implements BundleActivator { private ServiceRegistration serviceRegistration; @Override public void start( BundleContext context ) { this.serviceRegistration = context.registerService( MyInterface.class, new MyImpl(), new HashMap<String,String>()); } @Override public void stop( BundleContext context ) { if (serviceRegistration!=null) { serviceRegistration.unregister(); } } } 

    The bundle containing the activator and the implementation needs to import the package of the interface in its file MANIFEST.MF . 包含激活器和实现的捆绑软件需要将接口的包导入其文件MANIFEST.MF Neither the package of the activator or the implementation needs to be exported within this file. 激活程序的包或实现都不需要在此文件中导出。 They must remain internal to the bundle. 它们必须保持在捆绑包内部。

  • The class that consumes the service from another bundle 使用另一个捆绑软件中的服务的类

     public void callService() { ServiceReference<MyInterface> reference = bundleContext.getServiceReference(MyInterface.class); MyInterface foo = bundleContext.getService(reference); try { //use service String msg = service.shout(); } finally { bundleContext.ungetService( reference ); } } 

    You can notice that the consumers only requires to import the package of the interface (not the implementation one). 您会注意到,使用者仅需要导入接口的包(而不是实现的包)。 Moreover you need to be careful to handle dynamics of OSGi. 此外,您需要小心处理OSGi的动态。 The service could have gone between two calls! 该服务可能在两次通话之间就消失了!

Hope it helps you, Thierry 希望对您有帮助,蒂埃里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM