2014-11-05 449 views
0

我有一個項目,我正在使OSGi兼容的過程中。代碼依靠Java SPI來添加實現(META-INF/services)。我不想在OSGi環境中使用SPI(例如使用SPI Fly),我寧願使用OSGi方式。但是,我想要保持SPI對非OSGi環境的支持。我的方法是如下:結合OSGi和Java 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不兼容。這個限制大部分是可以管理的,但作爲一個通用的解決方案是不可接受的。

有沒有更好的方法?如果是這樣,怎麼樣?

回答

0

一種方法是明確地向MyDiscoverable提供通過newInstance創建的信息,例如, x.populateWithSPI()。這樣,setReference可以由實現本身用例如MyOtherFactory.newInstance()