首页 文章

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

提问于
浏览
0

我正在开发一个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,cardinality = ReferenceCardinality.MANDATORY_UNARY,bind =”bind“,unbind =”unbind“,referenceInterface = ServiceListener.class)private AtomicReference myServiceListener = new AtomicReference <>( );

如果我尝试在带有@Reference的另一个服务中使用它,则没有规定将值传递给服务以仅侦听特定的架构更改,以便可以通过仅传递架构列表来侦听服务而不是所有 . 因为一旦服务在使用类(组件)中正确绑定,就会调用activate方法 . OSGi中是否有任何规定可以实现此功能?

2 回答

  • 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
    }
    
  • 0

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

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

相关问题