使用Guice / Peaberry进行osgi声明性服务

时间:2015-02-12 08:27:31

标签: eclipse osgi guice equinox peaberry

我想解决以下问题并需要建议,最佳解决方案是什么。

我有一个捆绑A,其中定义了服务接口X.捆绑包B提供X的服务实现,并为该工具提供实现。 A和B使用Google Guice和Peaberry配置对象的设置。

我可以使用两种方式来提供服务实现:

  1. 使用eclipse扩展: 在这个解决方案中,我可以使用Peaberry的 GuiceExtensionFactory 机制来使用Guice创建服务实现,因此可以注入实现所需的东西。这里的缺点是在定义扩展点的bundle中,我需要用于解析扩展的样板代码,因为据我所知,没有办法将扩展注入到使用扩展的类中。 这看起来像这样:
  2. <extension point="A.service.X">
      <xservice
        ...
        class="org.ops4j.peaberry.eclipse.GuiceExtensionFactory:B.XImpl"
        .../>
    </extension>
    <extension
      point="org.ops4j.peaberry.eclipse.modules">
      <module
        class="B.XModule">
      </module>
    </extension>
    

    但我需要这样的样板代码:

    private List<X> getRegisteredX() {
        final List<X> ximpls = new ArrayList<>();
        for (final IConfigurationElement e : Platform.getExtensionRegistry().getConfigurationElementsFor(               X_EXTENSION_POINT_ID)) {
            try {
                final Object object = e.createExecutableExtension("class"); //$NON-NLS-1$
                if (object instanceof X) {
                    ximpls.add((X) object);
                }
            } catch (final CoreException ex) {
                // Log
            }
        }
        return ximpls;
    }
    
    1. 使用OSGI服务: 我的主要问题是确保服务已注册。我希望懒惰地加载捆绑包,因此至少需要访问捆绑包中的一个类。使用Peaberry以编程方式注册服务有一个问题,因为没有人要求提供一个类的捆绑。解决方案是将服务作为声明性服务提供,但我不知道以某种方式创建服务实现的方法,我可以使用Guice来注入所需的对象。
    2. 所以我有一些问题:

      1. 到目前为止,我是否有一些我不知道的东西,它实现了在扩展点一般读取扩展所需的代码,并允许使用扩展将扩展注入到类中?
      2. 是否有办法确保即使使用标准Peaberry机制添加服务也提供服务,即在请求服务时激活捆绑包?
      3. 是否有类似 GuiceExtensionFactory 的方式用于声明性服务,以便可以通过捆绑注入器来创建服务实现? 看起来像:
      4. <?xml version="1.0" encoding="UTF-8"?>
        <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Ximpl">
           <implementation class="some.generic.guiceaware.ServiceFactory:B.Ximpl"/>
           <service>
              <provide interface="A.X"/>
           </service>
        </scr:component>
        

        总结一下,我想要一个由Guice生成的服务实现,我希望使用没有大量样板代码的服务将服务实现简单地注入到类中。有人有解决方案吗?

        很抱歉,请问,但我在网上搜索了很长时间,到目前为止我找不到解决方案。

        谢谢和最诚挚的问候, 拉斯

1 个答案:

答案 0 :(得分:1)

我找到了一个解决方案,但是因为没有经过多次尝试而没有找到它,我想我在这里分享它。从我在发布中提到的选项中,我的解决方案使用第一个,即Eclipse扩展点和扩展。为了在扩展点的上下文中使用Guice,需要考虑两个方面:

提供由Guice注入器

创建的扩展

这里解释得非常好:https://code.google.com/p/peaberry/wiki/GuiceExtensionFactory。从我这边有一句话要说。扩展对象的创建是在GuiceExtensionFactory内部的注入器中完成的,因此它是一个自己的上下文,需要由作为工厂附加扩展的模块配置。如果您有其他需要需要在捆绑中创建注入器,这可能会成为一个问题。

定义扩展点,以便将扩展名简单地注入到使用扩展名的类中。

首先要做的是正常定义扩展点模式文件。它应该包含必须由扩展实现的接口的引用。

扩展点的id必须连接到扩展提供的接口,并由guice / peaberry注入。因此,peaberry提供了一个用于注释界面的注释:

import org.ops4j.peaberry.eclipse.ExtensionBean;

@ExtensionBean("injected.extension.point.id")
public interface InjectedInterface {
...
}

在某些网页上,您还可以找到以下信息:如果id等于接口的限定名称,则可以直接找到它而不使用注释,但我没有尝试过。

为了启用注射,您必须做两件事来配置Guice注射器的创建。

首先,必须将Peaberry的EclipseRegistry对象设置为ServiceRegistry。其次,必须完成扩展实现与提供的服务的绑定。

必须以这种方式完成注射器的创建:

import org.osgi.framework.BundleContext;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.ops4j.peaberry.eclipse.EclipseRegistry;

import static org.ops4j.peaberry.Peaberry.*;

void initializer() {
    Injector injector = Guice.createInjector(osgiModule(context, EclipseRegistry.eclipseRegistry()), new Module() {
               binder.bind(iterable(InjectedInterface.class)).toProvider(service(InjectedInterface.class).multiple());
        });
}

然后可以简单地注入扩展实现:

private Iterable<InjectedInterface> registeredExtensions;

@Inject
void setSolvers(final Iterable<InjectedInterface> extensions) {
    registeredExtensions = extensions;
}

通过所描述的方式,可以使用Guice注入扩展,这些扩展由类实现,以便注入依赖项。

到目前为止,我没有找到使用osgi服务的解决方案,但也许有人有想法。

祝你好运, 拉斯