【问题标题】:Pass runtime parameters to service in OSGi felix scr annotations将运行时参数传递给 OSGi felix scr 注释中的服务
【发布时间】:2017-12-19 03:01:23
【问题描述】:

我正在开发一个公开服务的 OSGi 应用程序(带有 felix scr 注释)。服务通过传递字符串值向外部 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 = “解除绑定”,referenceInterface = ServiceListener.class) private AtomicReference myServiceListener = new AtomicReference();

如果我尝试使用 @Reference 在另一个服务中使用它,则没有规定将值传递给服务以仅侦听特定架构更改,以便 通过仅传递模式列表而不是全部来侦听,可以在我的包中重新启动该服务。因为一旦服务在使用类(组件)中正确绑定,将调用激活方法。 OSGi 中是否有任何规定可以实现此功能?

【问题讨论】:

    标签: java osgi apache-karaf apache-felix


    【解决方案1】:

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

    从您共享的代码来看,您似乎遵循了一个非常糟糕的模式。侦听器模式是许多同步问题和内存泄漏的根源,在 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
    }
    

    【讨论】:

      【解决方案2】:

      一种方法是为每个架构创建一个服务。您可以通过提供模式名称作为配置值并使用多个配置来做到这一点。然后,每个此类服务还将将此配置参数作为服务属性。这样客户端就可以过滤架构属性了。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-27
        • 2021-07-14
        • 2010-10-02
        • 2018-05-18
        • 2017-07-29
        • 1970-01-01
        • 2011-10-15
        相关资源
        最近更新 更多