Java中的轻量级发布/订阅框架

48

有没有一个好的轻量级Java框架提供发布/订阅模式?

一些理想的特点:

  • 支持泛型
  • 注册多个订阅者到发布者
  • API主要是接口和一些有用的实现
  • 纯内存,不需要持久性和事务保证。

我知道JMS,但那对我的需求来说太过头了。发布/订阅数据是对文件系统进行扫描的结果,扫描结果被馈送到另一个组件进行处理,然后再被馈送到另一个组件进行处理,以此类推。

编辑: 所有这些操作都在同一个进程中完成。来自beans的PropertyChangeListener并不能完全胜任此任务,因为它报告的是属性的更改,而不是发布特定的项目。我可以通过具有“上次发布对象”属性的强制转换使ProprtyChangeListener起作用,从而发布对象。PropertyChangeListeners不支持泛型,并且深入了解属性更改语义,而不是纯粹的发布/订阅。java.util Observer/Observable模式是很好的选择,但Observer是一个具体类。


在一个进程内?还是跨越多个进程和机器? - djna
在单个进程内。 - mdma
这是一个Spring应用程序吗? - skaffman
@skaffman,是的,该应用程序是使用Spring实现的。我在这里关注的部分需要一个简单的发布/订阅模式,它是一个RIA客户端,使用Spring配置到Web服务端点的接口。被发布/订阅的对象都是本地的。 - mdma
我对JMS的引用有点困惑。如果您在单个进程中,一个或几个线程执行器池是否足够?如果线程是动态订阅的,那么在一系列BlockingQueue(s)周围使用松散包装器是否可行?线程可以通过从正确的队列中取出来选择订阅作业。当您的工作队列的某些部分比其他部分更快时,我曾经看到过各种JMS实现的性能问题。 - Gray
6个回答

32

看起来这个符合要求:

EventBus 来自Google Guava Library - “组件之间不需要显式地注册即可实现基于发布-订阅的通信”。它还可以是一个 AsyncEventBus ,将在另一个线程上调度事件。

还有一些额外的选择:

  1. 如果是在同一个进程中,可以考虑使用 观察者模式。 订阅者可以添加侦听器并接收事件通知。 Observable 已经是Java API的一部分。

  2. FFMQ 是一种全Java的,轻量级的,快速的JMS 1.1 Queue实现。


2
观察者模式似乎意味着对可观察对象和观察者的了解,而真正的发布/订阅允许代码独立性。Guava的EventBus在这方面看起来更好。 - unludo
另一个选择是使用MBassador——它类似于Guava EventBus,但声称具有更好的处理性能(请参见基准测试)。不过缺点是它看起来已经有一段时间没有更新了。 - msilb

11

JMS的轻重程度取决于您的配置。例如,在一个项目中,我们使用了HornetQ作为内存队列。它容易设置,不需要任何基于JNDI的配置,并且非常易于使用。

我认为,JMS作为消息发布/订阅的API就是最简单的方式。(并没有更简单的方式了;)


1
实际上,对于发布/订阅(也称为观察者)模式来说,最简单和最基本的东西就是javax.beans包。;)(PropertyChangeListener、PropertyChangeEvent、PropertyChangeSupport...) - user268396
@user268396,说得不错。对于简单的POJO状态改变pub/sub JavaBeans属性监听甚至更加简单。 - Timo Westkämper
@user268396 - 很抱歉,PropertyChangeListener 在这里不适用。请查看我的编辑以了解原因。 - mdma
谢谢这个建议。也许我在对JMS的评估上太仓促了? - mdma
@mdma,也许我以前也认为JMS是所有重量级J2EE的一部分,但如果您选择正确的提供程序,它实际上非常轻巧。如果接口/提供程序分离对您很重要,那么JMS可能是正确的方法。 - Timo Westkämper

8

由于您正在使用Spring,我不知道您是否知道Spring拥有自己的轻量级事件框架。它主要在框架内部使用,但应用程序代码也可以完美使用。

默认情况下,它是同步的发布/订阅,但您可以使用ApplicationEventMulticaster使其异步化。


1
我认为Camel也是一个不错的选择。特别是使用发布-订阅模式。Camel可以嵌入并且轻量级。它提供了企业集成模式 - 许多有用的工具,用于应用程序内部甚至与其他参与者(因此称为“集成”)。相较于Spring Integration而言,我认为更加完整。

0

如果您跨越进程边界,那么一定会产生某种程度的“重量”。为什么您说JMS很重?API非常简单?据说有轻量级实现,例如链接文本,更重的成本,如持久性和事务性是可选的。

您需要比这更轻的东西吗?


0
Bob Lee 在 http://snipt.org/GWm/ 写了一个 QueueFile 类,你可能会觉得它很有趣。它是一个简单的持久化队列,可以被多个消费者使用。听起来似乎你并不需要持久性,但由于整个东西非常轻量级,它仍然可能有用。

您可以从此处访问最新的实现:https://github.com/square/tape/blob/master/tape/src/main/java/com/squareup/tape/QueueFile.java - user452425

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接