2017-05-20 57 views
0

我有兩個包的OSGi包:方法訪問和非出口包

  1. com.organization.api這個包是出口。
  2. com.organization.internal此包未導出。

com.organization.api我有一個接口Foo和類AsbtractFoo

package com.organization.api; 

public abstract class AbstractFoo implements Foo { 

    private int state; 

    @Override 
    public int getState(){ 
     return this.state; 
    } 
} 

com.organization.internal我有一個類FooManager需要改變的Foo的狀態。如何使用com.organization.internal以外的任何其他類不能更改foo狀態的條件來執行此操作。

package com.organization.internal; 

public class FooManager { 

    private ???? foo = .... 

    public void updateFooState(){ 
     foo.????(); 
    } 
} 

我試圖添加AbstractStatefullFoo用的默認訪問(void setState(int state))設定器打包com.organization.internal和使AbstractFoo延伸AbstractStatefullFoo但問題是,這種情況下其它束需要包com.organization.internal導出。

這樣的問題在OSGi中如何解決?

回答

1

我有這樣的感覺,你正在考慮與所有這些抽象類複雜。

最簡單的情況是使用getState獲得一個接口Foo。 然後你在內部包中有一個Foo的實現。

這種情況下不需要其他包在內部訪問impl類。關鍵是在api包中也有FooManager的接口。

然後,您創建實現FooManager的FooManagerImpl並將其作爲服務與接口導出。其他bundle然後可以使用該服務來調用updateState()方法和其他操作FooImpl類的方法。

+0

謝謝你的回答,但我真的需要抽象類,因爲它們包含非常多的實現,它在其他包中的具體類中繼承。 –

+0

你也可以在兩者之間用抽象類來做到這一點。關鍵是使用OSGi服務,並讓其他bundle只使用api包中的類。 –

0

擴大上一個答案。

如果你封裝可變foo狀態並將工廠作爲服務公開,那麼可能會爲你簡化一些事情。爲了確保它們保持同步,將foo管理器服務作爲工廠可能是明智的。

FooState實現可以提供用於更改未包含在接口中並且對於實現包是私有的狀態的方法。 FooState接口應該標記爲不適用於Consumer實現。

可以更改Foo界面以允許訪問FooState。該對象是隻讀的(除非使用反射),但不是不可變的。您可以將訪問方法直接添加到Foo,或者您可以創建額外的導出接口,以避免不關心此問題的API用戶界面變得複雜。 AbstractFoo實現可以移動到單獨的導出包中。如果默認實現可能會生成受保護的方法並且通常比API本身更快地更改,那麼這可能很好,您不必經常碰撞API的版本。

抽象類可以負責獲取FooState以及其他實現支持任務。

如果您需要能夠在不更新Foos的情況下更新管理器實現,那麼可能會有一些額外的複雜情況,但這似乎不是一個要求。