我是OSGi的新手,我有兴趣将我的一些罐子改装为OSGi捆绑包。 但是,我不想为任何特定于osgi的库引入其他依赖项。
因为这样的注释是不可能的,因为程序化调用捆绑上下文而不是。
我发现声明性服务中的要求与我的要求接近匹配,这允许我公开我的低级别捆绑而不影响依赖性但是在更高级别(我实际上需要使用服务)我仍然有点卡住。
我知道组件xml可用于声明服务的实现(我已经用于我的低级jar),但也可以将服务实例注入特定的POJO。
现在我的问题是:如何访问osgi管理的POJO,其中注入了服务?是否可以在不引入新依赖项的情况下完成,或者我是否必须以编程方式执行此操作?
如果后者是这种情况可以有人指向我做某些代码的方向,换句话说,组件相当于bundleContext.getServiceReference()?
更新
澄清一下,如果您参加本教程的第五部分:http://www.vogella.com/articles/OSGiServices/article.html
他声明了一个component.xml文件,它使用引用绑定将服务注入到对象QuoteConsumer中。 好的,现在我怎么得到一个QuoteConsumer的实例,它注入了必要的服务,我不能很好地做“新的QuoteConsumer()”吧?
UPDATE2
目前我正在将osgi创建的实例注册为可以请求的静态变量,我认为这不是最好的方法,特别是因为我无法将构造函数设置为private。 (后者至少会产生一个真正的单身人士)
基本上,Factory类具有:
private void activate() {
instance = this;
}
UPDATE3
工厂的完整示例:
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加载一个或一个存根。 如有必要,您仍然可以手动设置服务实例。
UPDATE4
进一步澄清:这种模式不适用于从头开始设计在OSGi容器中运行的应用程序,而是适用于必须在任何地方运行的低级库,即使在OSGi容器上也不能假设所有消费者实际上都在使用OSGi。
答案 0 :(得分:2)
你听起来很混乱...... :-)服务是静态工厂的替代品,所以你的工厂不应该存在。
DS的全部思想是针对每个组件:
因此,无论何时获得由DS管理的服务,它都已经注入(绑定)其依赖项。因此,只要您保持服务依赖性,您就永远不需要静态工厂......服务的整体理念是您没有静态工厂,只能使用(注入)实例。 OSGi最好的部分之一就是你很少与工厂合作。
关于不使用注释的要求的一点评论。 OSGi注释只是类时间,它们不会创建运行时依赖项。我强烈建议使用它们,因为它们使服务像类一样轻量级,并且与XML相比是类型安全的。
使用注释而不是混乱代码的一个技巧是创建扩展您想要成为OSGi组件的实现类并在此类上添加注释。
答案 1 :(得分:1)
要访问服务,请从其他组件声明对它的引用:
@Reference
public void setFoo(Foo foo) {
this.foo = foo;
}
您可能会发现Bndtools tutorial有助于澄清这些概念。
答案 2 :(得分:0)
我说你走在正确的轨道上。如果方便的话,可以使用静态字段。
重要的是你让其余的代码处理QuoteConsumer出现并消失。因此,在您的激活器中放入代码,以便在QuoteConsumer可用时执行您需要执行的操作(在某些字段中注册,调用一些初始化代码,我不知道)并将您需要的代码置于停用状态,以指示QuoteConsumer已不再可用。