2015-11-02 90 views
0

我想用OSGI來完成某些東西,這些東西在Guice或Spring等依賴注入框架中非常直接。OSGI包可見服務實現

我想把服務實現類放到與服務接口相同的包中。這使我可以使用服務客戶端不關心的包可見方法。

Guice做到這一點的方法很簡單,使服務實現類包可見。服務接口:

package com.example.services; 

public interface SomeService { 

    void scanClasses(ServiceHelper helper); 
} 

和實現:

package com.example.services; 

// Package visible service implementation 
class SomeServiceImpl implements SomeService { 

    @Override 
    public void scanClasses(ServiceHelper helper) { 
     ClassLoader bundlesClassLoader = helper.getClassLoader(); 
     // do something with bundle's classes 
    } 

} 

這是ServiceHelper類裏面也有包可見的方法:

package com.example.services; 

import org.osgi.framework.BundleContext; 
import org.osgi.framework.wiring.BundleWiring; 

public class ServiceHelper { 
    private ClassLoader bundleClassLoader; 

    public ServiceHelper(BundleContext bc) { 
     this.bundleClassLoader = bc.getBundle().adapt(BundleWiring.class).getClassLoader(); 
    } 

    // Package visible method to be called from SomeServiceImpl class 
    ClassLoader getClassLoader() { 
     return bundleClassLoader; 
    } 

} 

但是OSGI無法實例ServiceImpl類包可見的decleration或構造函數:

java.lang.IllegalAccessException:類org.eclipse.equinox.internal.ds.model.ServiceComponent不能訪問類com.example.SomeServiceImpl的成員與改性劑「」

而完成的實例中,這是服務客戶端代碼,這不應該由設計的影響:

package com.example.serviceclient; 

import org.osgi.framework.BundleContext; 

import com.example.services.ServiceHelper; 
import com.example.services.SomeService; 

public class ServiceClientExample { 

    private SomeService someService; 

    public void activate(BundleContext bc) { 
     someService.scanClasses(new ServiceHelper(bc)); 
    } 

    public void setSomeService(SomeService service) { 
     this.someService = service; 
    } 
} 

把服務落實到另一個包,並試圖建立良好的面向對象的封裝需要太多的工作,如它映射的訪問類的東西給調用者打包可見方法,我相信應該有另外一種方法。

+0

你試圖破壞基於軟件包的OSGI輸出和輸入。客戶端總是需要導入接口的包,所以這個包必須在OSGi中導出。該實現不應該導出。所以即使你可以解決你的問題,你也應該總是使用單獨的包來接口和impl。 –

回答

2

您正在使用OSGi聲明式服務,它要求實現類是公開的,並且具有公共的零參數構造函數。這是設計。您可以通過使用BundleActivator並在代碼中實例化該組件來解決此問題,但僅有很少的一點...

如果您的實現類與接口位於同一個包中,那麼接口的每個客戶端都會直接耦合到實現類。所以你可能只需要公開實現類並允許客戶端直接實例化它。

OSGi允許真實分離合同,提供者和消費者。將合同和供應商合併到同一個軟件包中會使其失敗。 Guice和Spring將這些概念聯繫在一起的「直截了​​當」這一事實既不存在,也不存在。

+0

我同意尼爾。爲什麼要麻煩製作一個界面? –

+0

我相信,包可見類,即使包本身被導出也不能用於客戶端,提供了一個簡單的封裝。並且在導出的包中隱藏方法沒有簡單的方法,只是爲了從服務實現中訪問而公開它們更容易。但我想這是OSGI的主要設計決定,所以我必須接受答案。 – b10y