我正在开发一个公开服务的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中是否有任何规定可以实现此功能?
答案 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方法中提供模式名称来创建实例。