2015-11-16 73 views
1

如何確保在調用activate()之前注入所有依賴項?激活後OSGI聲明性服務注入

private IMyDependency aInstance, bInstance, cInstance; 

    public void setDependency(IMyDependency depInstance) { 

     Bundle depBundle = FrameworkUtil.getBundle(depInstance.getClass()); 

     logger.debug("Dependency {} from bundle {} retrieved", depInstance, depBundle.getSymbolicName()); 

     if (A_BUNDLE_NAME.equals(depBundle.getSymbolicName())) { 
      aInstance = depInstance; 
     } else if (B_BUNDLE_NAME.equals(depBundle.getSymbolicName())) { 
      bInstance = depInstance; 
     } else if (C_BUNDLE_NAME.equals(depBundle.getSymbolicName())) { 
      cInstance = depInstance; 
     } else { 
      logger.error("Dependency {} from unknown bundle {}", depInstance, depBundle); 
     } 
    } 

    public void activate() { 
     Preconditions.checkNotNull(aInstance); 
     Preconditions.checkNotNull(bInstance); 
     Preconditions.checkNotNull(cInstance); 
     //... 
    } 

有IMyDependency的多個實例,並且依賴基數是0..n

問題是,setDependency()有時在activate()方法後調用。解決方法是更改​​從屬捆綁的開始級別,但我們確實不想觸摸配置。

+1

只有在所有三種依賴關係都可用的情況下,纔想激活組件?爲什麼不在組件中創建三個單獨的引用? –

+0

不完全。我希望框架能夠在所有依賴關係被注入後激活組件。組件中已經有三個單獨的引用。 – b10y

+1

根據您的示例代碼,您需要三個單獨的STATIC參考和MANDATORY基數,而不是有一個0..n參考。根據他們來自哪個捆綁的事實連接OSGi服務是一種非常糟糕的做法。另外,請參閱Declarative Services新規範中的最小基數選項(我不知道這是否已在新的SCR項目中實現)。 「 –

回答

1

隨着Balazs '評論,我才得以改觀0..n依賴到3個明確1..1依賴關係:

<reference bind="setDependencyA" cardinality="1..1" interface="com.example.IMyDependency" name="DepA" policy="static" target="(dependencyType=A)"/> 
<reference bind="setDependencyB" cardinality="1..1" interface="com.example.IMyDependency" name="DepB" policy="static" target="(dependencyType=B)"/> 
<reference bind="setDependencyC" cardinality="1..1" interface="com.example.IMyDependency" name="DepC" policy="static" target="(dependencyType=C)"/> 

相關類:

public void setDependencyA(IMyDependency depInstance) { 
     aInstance = depInstance; 
    } 

    public void setDependencyB(IMyDependency depInstance) { 
     bInstance = depInstance; 
    } 

    public void setDependencyC(IMyDependency depInstance) { 
     cInstance = depInstance; 
    } 

而且我也不得不改變依賴' 激活(不幸的是依賴關係不使用DS):

@Override 
public void start(BundleContext context) throws Exception { 
    Hashtable<String, String> props = new Hashtable<>(); 
    props.put("dependencyType", "A"); 
    srvReg = context.registerService(IMyDependency.class.getName(), myInstance, props); 
} 
0

普通OSGi在管理依賴方面非常堅定。你應該明確你的依賴鏈。通過實施智能服務跟蹤器,您可以獲得更多動態,從而延遲您的初始化,直到您的所有依賴關係都可用。不過,我建議你使用聲明式服務來避免老式的依賴注入。

+0

」但是,我建議你使用聲明式服務來避免老式的依賴注入。「:根據問題的標題,我猜b10y已經使用了聲明式服務。 –

0

我想你想要的是一種插件系統。所以你知道界面,但你不知道有多少impls,但你想確保所有的都加載,直到你加載。

這在OSGi中並不那麼容易。事實上,一個附加服務可能會在運行時發生。所以一個解決方案就是簡單地適應服務的所有變化。在某些情況下,這是不夠的。

例如,我有一個案例,我想提供安全插件到我的應用程序。如果沒有安全性插件,我的包就會啓動,但它應該是可配置的,這是不可接受的。

所以我做了什麼是給每個插件使用OSGi屬性的名稱,並在插件機制中允許列出所有插件的名稱以加載到配置pid中。該機制確保主應用程序只在所有命名插件存在時才啓動。不幸的是,這樣的機制不是內置到DS中,但您可以使用綁定和解除綁定方法來實現它。

1

現在與標註全成分:

@Component public class MyComponent { 

    @Reference(target="(dependencyType=A)") IMyDependency aInstance; 
    @Reference(target="(dependencyType=B)") IMyDependency bInstance; 
    @Reference(target="(dependencyType=C)") IMyDependency cInstance; 


    @Activate public void activate() { 
    // all guaranteed set 
    } 
} 

實例組件:

@Component public class MyDependency implements IMyDependency { 
    ... 
} 

而且你應該使用configuration創建3個實例。