我对OSGi以及与此接近的一切都很陌生。
跳进问题:我有一个服务器类,它保存一个监听器列表,监听器可以通过一个方法(register(this)
)注册它们,该方法将监听器放入上面提到的列表中(所有监听器都实现了当然是服务器级的监听器接口:
public void register(ServerListener listener) {
if(theListeners == null)
theListeners = new ArrayList<ServerListener>();
theListeners.add(listener);
}
那是ServerListener
界面:
public interface ServerListener {
public void update(JsonObject data);
}
现在,服务器类通过update(JsonObject object)
方法不时向听众提供新数据。
public void updateListeners() {
new Thread() {
public void run() {
for(ServerListener l : theListeners) {
l.update(jsonObject);
}
}
}.start();
}
现在,我想将服务器类修改为OSGi框架(Knopflerfish)中的服务包。我根本不熟悉。我想尝试只是为了好玩,但我现在这样做的方式不起作用,听众实际上并不知道他们应该实现ServerListener
接口。因此服务器无法通过接口注册它们。
问题是,我想服务器推送数据,而不是客户端拉(根据我的理解,这会更容易)。某人(他理解我的不良解释)能指出我正确的方向吗?
答案 0 :(得分:6)
'以OSGi为中心'的方法是使用称为白板模式的模式,而不是像普通Java那样使用监听模式。您的侦听器不是使用服务器类注册,而是使用OSGi服务注册表注册为服务。这意味着该框架负责处理注册,注销和听众的处理。
这里有一个关于白板模式的免费白皮书:http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf,我们还在 Enterprise OSGi in Action (http://www.manning.com/cummins的第5章中对它进行了讨论。 )。
可能需要一段时间才能让你的头部围绕听众模式,因为它是你的听众提供服务,而你的'服务器'消耗服务,起初感觉倒退。但是,一旦你习惯它,它的效果非常好。您的服务器使用实现ServiceListener接口的所有服务,并根据需要将数据推送到它们。
最好不要直接使用OSGi API来注册和使用服务 - 使用声明性服务(SCR)或蓝图来依赖注入OSGi服务。这些允许您使用XML元数据文件或注释注册和使用服务。
(正如其他人所建议的那样,使用ServerListener接口的包级依赖项应该允许服务器和侦听器包导入它,无论哪个bundle导出包。)
答案 1 :(得分:4)
你在这里遇到了多个问题:
一般来说,尝试将现有代码改装到OSGi中可能会很痛苦,除非您已经拥有模块化架构。
侦听器接口可以存在于服务器包中,也可以将其放在单独的API /合约包中 - 两者都是有效的设计。
从描述问题的方式来看,您可能不知道OSGi中可能存在的不同类型的依赖关系。
来自传统的Java开发,大多数开发人员将从“我的依赖项基于JAR”开始 - 这不是最好的模型。
OSGi提供包级依赖性。通过这种方式,只要一些bundle提供了所需的包,你就是bundle并不关心哪个bundle / JAR提供了依赖。
因此,如果您对侦听器接口使用了包级依赖关系,则实现不需要关心它是来自服务器包还是合同/ API包。
最后一点,您的设计将服务器与听众紧密联系在一起。如果听众失败会怎么样?还是挂? Pub / sub是这种通信的更好模型。
*编辑*
霍莉的回答再次提醒我白板模式 - 绝对是个好主意。