我是 OSGi 的新手,我有兴趣将我的一些 jar 改装为 OSGi 包。但是,我不想为任何 osgi 特定的库引入额外的依赖项。
因为这样的注释是不可能的,对捆绑上下文的编程调用也是不可能的。
我发现声明式服务与我的要求几乎匹配,这允许我在不影响依赖关系的情况下公开我的较低级别的捆绑包,但是在更高级别(我实际上需要使用服务)我仍然有点卡住。
我知道组件 xml 可用于声明服务的实现(我已经将其用于我的较低级别的 jar),也可用于将服务实例注入特定的 POJO。
现在我的问题是:如何访问已注入服务的 osgi 管理的 POJO?在不引入新依赖项的情况下是否有可能,或者我必须以编程方式进行?
如果是后者,有人可以指点我一些代码的方向来做到这一点,换句话说,bundleContext.getServiceReference() 的组件等效项?
更新
澄清一下,如果您阅读本教程的第五部分:http ://www.vogella.com/articles/OSGiServices/article.html
他声明了一个 component.xml 文件,该文件使用引用绑定将服务注入到 QuoteConsumer 对象中。太好了,现在我如何获得一个注入了必要服务的 QuoteConsumer 实例,我不能很好地执行“new QuoteConsumer()”,对吗?
更新2
目前我正在将 osgi 创建的实例注册为可以请求的静态变量,我认为这不是最好的方法,尤其是因为我无法将构造函数设置为私有。(后者至少会产生一个真正的单例)
基本上工厂类有:
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;
}
}
然后任何客户端代码都可以执行以下操作:
Factory.getInstance().getMyInterface();
并接收 OSGi 加载的服务、SPI 加载的一个或一个存根。如有必要,您仍然可以手动设置服务实例。
更新4
进一步澄清:此模式不适用于从头开始设计为在 OSGi 容器中运行的应用程序,而是用于必须在任何地方运行的低级库,即使在 OSGi 容器上也不能假定所有消费者都是实际使用 OSGi。