番石榴的EventBus –简单的发布者/订阅者

在查看Google的Guava Libraries 版本10的最新版本时,我注意到EventBus的添加。 这是发布-订阅样式消息传递系统的轻量级实现。 这类似于JMS提供的发布-订阅模型,但是消息保留在应用程序内,而不是在外部广播。

EventBus允许您在程序中创建对象可以订阅的流; 然后,他们将接收发布到这些流的消息。 尽管使用诸如单例之类的模式来重新创建对象间通信并不是特别困难,但EventBus确实提供了一种特别简单且轻巧的机制。 单例还使具有单一类型的多个事件总线更加困难,并且
很难测试。

例如,我将使用几个人将通过telnet连接到的套接字创建一个简单的多用户聊天程序。 我们将简单地创建一个EventBus作为通道。 用户发送给系统的任何消息都将发布给所有其他用户。

所以这是我们的UserThread对象:

class UserThread extends Thread {
    private Socket connection;
    private EventBus channel;
    private BufferedReader in;
    private PrintWriter out;

    public UserThread(Socket connection, EventBus channel) {
        this.connection = connection;
        this.channel = channel;
        try {
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            out = new PrintWriter(connection.getOutputStream(), true);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Subscribe
    public void recieveMessage(String message) {
        if (out != null) {
            out.println(message);
        }
    }

    @Override
    public void run() {
        try {
            String input;
            while ((input = in.readLine()) != null) {
                channel.post(input);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //reached eof
        channel.unregister(this)
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        in = null;
        out = null;
    }
}

可以看出,这只是一个简单的线程对象,其中包含充当通道的EventBus和用户的Socket。 然后,run方法通过调用EventBus上的post方法简单地读取套接字并将消息发送到通道。

然后,通过添加带有@Subscribe批注的公共方法来实现接收消息(请参见上文)。 这表示EventBus在收到方法参数中给定类型的消息后调用此方法。 我在这里发送字符串,但是可以使用其他对象。

GOTCHA :用@Subscribe注释的方法必须是公共的。

接收功能接收消息并将其写出到用户的连接中。 当然,这还将回送已发送给原始用户的消息,因为UserThread对象本身将接收其发布的消息。

剩下的就是创建一个简单的服务器对象,该对象侦听连接并根据需要创建UserThread对象。

public class EventBusChat {
    public static void main(String[] args) {
        EventBus channel = new EventBus();
        ServerSocket socket;
        try {
            socket = new ServerSocket(4444);
            while (true) {
                Socket connection = socket.accept();
                UserThread newUser = new UserThread(connection, channel);
                channel.register(newUser);
                newUser.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如图所示,这将创建通道,接受用户连接并将其注册到EventBus。 这里要注意的重要代码是使用UserThread对象作为参数调用register方法。 该调用在EventBus上预订对象,并指示它可以处理消息。

服务器启动后,用户即可使用telnet命令连接到聊天服务器:

telnet 127.0.0.1 4444

而且,如果您连接多个实例,您将看到发送的任何消息都被中继到其他实例。

看完此示例后,您可能想知道EventBus有什么用。 一个很好的例子是在用户界面和后端代码之间保持非常松散的耦合。 用户输入将生成一条消息,例如调整大小,失去焦点或关闭。 然后,后端组件可以简单地订阅这些事件并适当地处理它们。 官方文档还列出了许多其他用途。

注意: EventBus并非用于通用的发布者-订阅者通信,这只是API交互方式的一个示例。

原文: http//insightfullogic.com/blog/2011/oct/10/eventbus/

参考: Guava的EventBus –来自我们LCG博客Java用户组的 JCG合作伙伴 Andriy Andrunevchyn的简单发布者/订阅者

翻译自: https://www.javacodegeeks.com/2013/06/guavas-eventbus-simple-publishersubscriber.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值