我有一个项目,我正在使OSGi兼容的过程中。代码依赖于Java SPI来添加实现(META-INF/services)。我不想在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注释(或者更确切地说,是从它生成的声明性服务)填充引用。
如果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不兼容。这个限制在很大程度上是可以管理的,但作为一般的解决方案是不可接受的。
有没有更好的方法?如果是这样的话,是怎么做的?
发布于 2014-11-08 02:00:31
一种方法是显式地向MyDiscoverable提供它是通过newInstance创建的信息,例如x.populateWithSPI()。这样,实现本身就可以用MyOtherFactory.newInstance()调用setReference。
发布于 2018-07-23 22:42:52
OSGI使用IOC容器,并且像所有IOC容器(Guice、Spring等)一样,IOC容器必须负责类的实例化。
SPI支持在运行时发现实现,并且SPI将这些实现实例化为发现的一部分。
您无法将同一个类用于SPI和OSGI (或任何其他IOC容器),因为它们有不同的实例化类的方法。我建议将这两种方法分开。
您可以围绕SPI使用的MyFactoryService创建一个包装类。这个类可以被称为MyFactoryServiceProvider,它可以返回一个类引用供MyFactoryService实例化,然后将MyDiscoverable的引用传递给它。
https://stackoverflow.com/questions/26764903
复制相似问题