在OSGi felix scr注释中将运行时参数传递给服务

时间:2017-07-14 06:00:17

标签: java osgi apache-karaf apache-felix

我正在开发一个公开服务的OSGi应用程序(使用felix scr annotations)。服务通过传递String值来注册外部api。

listener.addSchemaChangeListener(new ChangeListener()
{
    @Override
    public void schemaChange(ChangeEvent changeEvent)
    {
        String schemaName = changeEvent.getSchemaName();

        if (null != myBuilder && schemaList.contains(schemaName))
        {
            initVariables();
        }
    }
}, "SCHEMA1");

服务使用上面的代码来注册多个值的监听器" SCHEMA1"," SCHEMA1"," SCHEMA3" ... 我计划在各种捆绑包中重用此服务。但我想只听取SCHEMA1的变化,而不是全部。

  

@Reference(name =" ServiceListener"",policy =   ReferencePolicy.DYNAMIC,基数=   ReferenceCardinality.MANDATORY_UNARY,bind =" bind",unbind =   " unbind",referenceInterface = ServiceListener.class)       private AtomicReference myServiceListener = new AtomicReference<>();

如果我尝试在带有@Reference的其他服务中使用它,则没有规定将值传递给服务以仅侦听特定的架构更改,以便 只需将模式列表传递给listen而不是all,就可以在我的bundle中重新发送服务。因为一旦服务在使用类(组件)中正确绑定,就会调用activate方法。 OSGi中是否有任何规定可以实现此功能?

2 个答案:

答案 0 :(得分:3)

您对应用程序实际工作方式的描述很少,这使得这个问题难以回答。

从您共享的代码看起来好像您正在遵循相当糟糕的模式。监听器模式是许多同步问题和内存泄漏的来源,当您在OSGi中时,应首选白板模式。

白板图案非常简单。您可以反转模型,而不是让每个侦听器查找服务并向其注册。事件源(在本例中为架构更改)查找在OSGi服务注册表中注册的侦听器服务。这样,监听器就可以很容易地编写和过滤,并且没有杂乱且容易出错的添加/删除监听器逻辑来编写代码。

更好的模型将使用服务属性来选择特定模式,并使用标准的OSGi注释(

)。

侦听器1(侦听SCHEMA1的更改)

@Component(
    property="schemaName=SCHEMA1")
public class MyListener implements ChangeListener {
    // Your implementation in here
}

侦听器2(侦听SCHEMA1,SCHEMA2和SCHEMA3的更改)

@Component(
    property={"schemaName=SCHEMA1",
              "schemaName=SCHEMA2",
              "schemaName=SCHEMA3"})
public class MyListener implements ChangeListener {
    // Your implementation in here
}

示例Schema1的事件源:

@Component
public class MyListener implements ChangeListener {

    @Reference(policy=DYNAMIC, target="(schemaName=SCHEMA1)")
    private final List<ChangeListener> listeners = new CopyOnWriteArrayList<>();

    private void onSchemaChange(ChangeEvent event) {
        listeners.forEach(l -> l.schemaChange(event);
    }

    // Rest of your implementation in here
}

答案 1 :(得分:0)

一种方法是为每个架构创建一个服务。您可以通过提供架构名称作为配置值并使用多个配置来完成此操作。然后,每个这样的服务也将该配置参数作为服务属性。因此,客户端可以过滤架构属性。

如果您不想使用这些配置,那么您可以创建一个提供工厂的服务。然后,每个客户端将绑定工厂并通过在工厂的create方法中提供模式名称来创建实例。