Java 使用OSGi将组件注入POJO

Java 使用OSGi将组件注入POJO,java,osgi,Java,Osgi,我是OSGi新手,我有兴趣将我的一些JAR改装成OSGi捆绑包。 但是,我不想为任何osgi特定的库引入额外的依赖项 这样的注释是不可能的,对捆绑上下文的编程调用也是不可能的 我在声明性服务中发现了一个与我的需求几乎匹配的东西,它允许我公开较低级别的bundle而不影响依赖关系,但是在较高级别(我实际上需要使用服务的地方),我仍然有点卡住了 我知道,组件xml可以用于声明服务的实现(我已经将其用于较低级别的JAR),也可以用于将服务实例注入到特定的POJO中 现在我的问题是:如何访问osgi管理

我是OSGi新手,我有兴趣将我的一些JAR改装成OSGi捆绑包。 但是,我不想为任何osgi特定的库引入额外的依赖项

这样的注释是不可能的,对捆绑上下文的编程调用也是不可能的

我在声明性服务中发现了一个与我的需求几乎匹配的东西,它允许我公开较低级别的bundle而不影响依赖关系,但是在较高级别(我实际上需要使用服务的地方),我仍然有点卡住了

我知道,组件xml可以用于声明服务的实现(我已经将其用于较低级别的JAR),也可以用于将服务实例注入到特定的POJO中

现在我的问题是:如何访问osgi管理的POJO,该POJO中注入了服务?在不引入新的依赖项的情况下,这是完全可能的,还是我必须以编程的方式来实现

如果是后一种情况,有人能告诉我一些代码的方向吗?换句话说,就是bundleContext.getServiceReference()的等效组件

更新

为了澄清,如果您学习本教程的第五部分:

他声明了一个component.xml文件,该文件使用引用绑定将服务注入到对象QuoteConsumer中。 太好了,现在我如何获得一个QuoteConsumer实例,该实例中注入了必要的服务,我不能很好地执行“new QuoteConsumer()”对吗

更新2

目前,我正在将osgi创建的实例注册为可以请求的静态变量,我认为这不是最好的方法,特别是因为我无法将构造函数设置为private。(后者至少会产生一个真正的单身汉)

基本上,Factory类具有:

private void activate() {
    instance = this;
}
更新3

工厂的完整示例:

public class Factory {

    private static Factory instance;

    public static Factory getInstance() {
        if (instance == null)
            instance = new Factory();
        return instance;
    }

    private MyInterface implementation;

    public void setMyInterface(MyInterface implementation) {
        this.implementation = implementation;
    }

    public void unsetMyInterface(MyInterface implementation) {
        implementation = null;
    }

    public MyInterface getMyInterface() {
        if (implementation == null) {
            ServiceLoader<MyInterface> serviceLoader = ServiceLoader.load(MyInterface.class);
            Iterator<MyInterface> iterator = serviceLoader.iterator();
            if (iterator.hasNext())
                implementation = iterator.next();
            else
                implementation = new MyInterfaceStub();
        }
        return implementation;
    }

    @SuppressWarnings("unused")
    private void activate() {
        instance = this;
    }
    @SuppressWarnings("unused")
    private void deactivate() {
        instance = null;
    }
}
并接收OSGi加载的服务、SPI加载的服务或存根。 如果需要,您仍然可以手动设置服务实例

更新4


进一步澄清:此模式并不适用于从一开始就设计为在OSGi容器中运行的应用程序,而是适用于必须在任何地方运行的低级库,即使在OSGi容器上也不能假设所有使用者都在实际使用OSGi。

访问服务,您可以从另一个组件声明对它的引用:

@Reference
public void setFoo(Foo foo) {
    this.foo = foo;
}

您可能会发现这将有助于澄清这些概念。

我认为您的思路是正确的。如果方便的话,可以使用静态字段

重要的是,您要让代码的其余部分处理QuoteConsumer的出现和消失。因此,在激活器中输入代码,以便在QuoteConsumer可用时执行您需要执行的操作(在某个字段中注册它,调用一些初始化代码,我不知道),然后输入停用代码,以指示QuoteConsumer不再可用。

您听起来很困惑…:-)服务是静态工厂的替代品,因此您的工厂不必存在

DS的整体理念是,对于每个组件:

@Reference
public void setFoo(Foo foo) {
    this.foo = foo;
}
  • 等待直到满足其依赖关系
  • 创建一个实例
  • 将实例绑定到其依赖项
  • 在实例上调用activate
  • 将实例注册为服务
  • 因此,每当您获得由DS管理的服务时,它就已经被注入(绑定)其依赖项。因此,只要您保持服务依赖性,就永远不需要静态工厂。。。服务的整体思想是,您没有静态工厂,只能使用(注入的)实例。OSGi最好的部分之一是您很少与工厂合作

    关于不使用注释的要求的一点意见。OSGi注释仅在类时使用,它们不会创建运行时依赖项。我强烈建议使用它们,因为它们使服务像类一样轻量级,并且与XML相比是类型安全的


    使用注释而不使代码混乱的一个技巧是创建扩展您想要成为OSGi组件的实现类,并在此类上添加注释。

    代码目前基本上允许三种操作模式:OSGi、SPI和手动设置,而不引入新的依赖项。因此,如果OSGi实例被删除(或者从一开始就不存在),它将退回到SPI,如果这不起作用,您将负责自己管理它。我将用示例代码更新原始问题谢谢您的反馈。工厂实现背后的原因是模块应该在任何环境中运行。因此,一般来说,我的所有模块都“期望”管理注入,但如果没有发生这种情况,则应该回到工厂模式。但是让工厂支持OSGi可能有点傻,它可以只使用SPI:),除非你正在改造一个现有工厂,该工厂由未启用OSGi的模块使用?好吧,在OSGi世界中,事情似乎非常简单和直接:每个对象都是一个组件。因此,在非OSGi的世界中,您需要一些DI引擎来进行注入。