【问题标题】:Combining OSGi with Java SPI将 OSGi 与 Java SPI 相结合
【发布时间】:2015-01-02 02:23:33
【问题描述】:

我有一个项目正在使 OSGi 兼容。该代码依赖于 Java SPI 来添加实现(META-INF/服务)。我不想在 OSGi 环境中使用 SPI(例如通过使用 SPI Fly),我宁愿使用 OSGi 方式。但是,我想保持对非 OSGi 环境的 SPI 支持。我的方法如下:

工厂看起来像这样(使用 BND 注释):

@Component
class MyFactory implements MyFactoryService {

    public MyFactory() {
         ...
    }

    //This method is reserved for non-OSGi use (uses SPI to find implementations)
    public static MyFactory newInstance() {
        MyFactory ret = new MyFactory();
        Iterator<MyDiscoverable> i = ServiceLoader.load(MyDiscoverable.class).iterator();
        while (i.hasNext()) {
            ret.addFactory(i.next());
        }
    }

    @Reference
    public void addFactory(MyDiscoverable f) {
        ...
    }

}

在 OSGi 上下文中,MyFactory 位于 OSGi 私有包中,必须使用 MyFactoryService 接口通过服务注册表检索。然后 OSGi 框架使用 @Reference 注释(或者更确切地说是从它生成的声明性服务)填充 MyFactory。

如果 MyDiscoverable 的实现需要其他类似于 MyFactory 的工厂,我在 MyFactory.newInstance() 中放了这样的东西:

 public static MyFactory newInstance() {
        MyFactory ret = new MyFactory();
        MyOtherFactory other = MyOtherFactory.newInstance();
        Iterator<MyDiscoverable> i = ServiceLoader.load(MyDiscoverable.class).iterator();
        while (i.hasNext()) {
            MyDiscoverable x = i.next();
            //This method is also annotated with @Reference in the implementation, to support OSGi use
            x.setReference(other);
            ret.addFactory(x);
        }
}

这在 OSGi 和 SPI 上下文中都可以正常工作。我遇到的一个问题是工厂必须知道每个实现可能需要哪些其他工厂(并提供它们)。这是因为我还没有找到一种方法来让实现创建自己的工厂实例而不使其与 OSGi 不兼容。这种限制在大多数情况下是可以控制的,但作为一般解决方案是不可接受的。

有没有更好的方法?如果有,怎么做?

【问题讨论】:

    标签: java design-patterns osgi


    【解决方案1】:

    一种方法是明确地向 MyDiscoverable 提供它是通过 newInstance 创建的信息,例如。 x.populateWithSPI()。这样,setReference 可以由实现本身调用,例如MyOtherFactory.newInstance()

    【讨论】:

      【解决方案2】:

      OSGI 使用 IOC 容器,与所有 IOC 容器(Guice、Spring 等)一样,IOC 容器必须负责类的实例化。

      SPI 支持在运行时发现实现,并且 SPI 将这些实现实例化为发现的一部分。

      你不能在没有 hack 的情况下为 SPI 和 OSGI(或任何其他 IOC 容器)使用相同的类,因为它们有不同的实例化类的方法。我建议将这两种方法分开。

      您可以围绕MyFactoryService 创建一个包装类,供SPI 使用。该类可以称为MyFactoryServiceProvider,它可以返回MyFactoryService 的类引用供您实例化,然后将MyDiscoverable 的引用传递给它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-02
        • 2012-05-19
        • 2020-05-04
        • 1970-01-01
        • 2014-10-23
        • 2011-08-11
        • 2011-11-13
        • 2013-04-13
        相关资源
        最近更新 更多