Guava的event bus

guava, https://github.com/google/guava 是一个非常有名的Java类库,提供了很多在日常开发中常用的集合、函数接口等。此外,guava还提供了一个模块叫做event bus,生产者往event bus上投递消息,event bus负责回调订阅了此类消息的回调函数,实现了消息生产者和消费者之间的解耦和异步处理。以下是一个简单的例子:

public class SimpleListener {
@Subscribe
public void task(String s) {
System.out.println("do task(" + s + ")");
}
}
public class SimpleEventBusExample {
public static void main(String[] args) {
EventBus eventBus = new EventBus();
eventBus.register(new SimpleListener());
System.out.println("Post Simple EventBus Example");
eventBus.post("Simple EventBus Example");
}
}

output

Post Simple EventBus Example
do task(Simple EventBus Example)

event bus集成到spring中

在之前的例子和guava的官方文档里面可以看到,guava的event bus使用方式如下

1. 声明一个event bus对象(线程安全,所以可以做到全局唯一,而且订阅者和发布者必须共享这个event bus对象)

2. 对于订阅者,支持 @Subscribe,定义处理消息的回调函数。

3. 对每一个订阅者,需要调用event bus的register方法,才能收到消息订阅。

对于1 和 2,都比较好。但是对于第3步来说,则有一点困难。因为

1. 在spring中,通常的你的订阅者还会依赖其他的spring管理的bean,于是你的订阅者也会被纳入到spring的生命周期的管理中来,这样如果用new的方式来初始化一个订阅者,显得非常的"不spring"。

2. 对于每个订阅者,都要显式的注册到event bus里面,这样并没有做到关注点分离。理想的情况下,订阅者是不应该去关注如何注册到event bus中。它只应该申明处理消息的回调函数,以及该回调函数是否能够并发调用。注册到event bus中这件事,对于订阅者应该是被动且自动的(只需要申明自己是否想注册到event bus,而不需要关心细节)。这一点在多人开发,并且项目人员水平参差不齐的时候,尤其重要。

那么如何做到自动注册呢?其实答案很简单,在spring中,ApplicationContext这个类提供了一系列的方法去获取到当前spring context中的bean,只需要在event bus初始化之后,通过ApplicationContext来获取当前有哪些订阅者,并且主动的去注册就行。由于,guava的实现中,并没有要求订阅者实现某个接口,而是用注解的方式来声明回调函数的,则这篇文章中的实现,也不需要订阅者去实现某个接口,而是用注解的方式来申明自己是一个订阅者。代码如下

先声明一个注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface EventSubscriber {}

对于一个订阅者,在类的接口上,加上这个注解,并且确定这个bean会在纳入spring的生命周期管理中。

@EventSubscriber
public class SimpleSubscriber implements HiDasSubscriber {
@Autowired
Somebean somebean; @Subscribe
@AllowConcurrentEvents
public Integer logEventToDbAndUpdateStatus(String event) {
System.out.println("receive a event:"+event);
}
}

声明一个event bus的服务,并且在初始化之后,通过ApplicationContext的 getBeansWithAnnotation 的方法把所有的订阅者获取,并且注册到event bus中。

@Service
public class EventBusService implements InitializingBean{ private EventBus innerBus; @Inject
private ApplicationContext appContext; public void unRegister(Object eventListener){
innerBus.unregister(eventListener);
} public void postEvent(String event){
innerBus.post(event);
} public void register(Object eventListener){
innerBus.register(eventListener);
} @Override
public void afterPropertiesSet() throws Exception {
innerBus = new AsyncEventBus("Hidas-event-bus", Executors.newCachedThreadPool());
appContext.getBeansWithAnnotation(EventSubscriber.class).forEach((name, bean) -> {
innerBus.register(bean);
});
}
}

完成了这两步之后。如果其他的消息生产者要往event bus上发消息,只需要注入这个event bus service,并且调用其post方法就好了。

注:这个只是例子,在实际项目中,对所有的消息都会声明一个基类或者接口,每个订阅者对只会处理消息的某个具体实现。这样event bus会根据消息的具体类型,来调用真正关注此类消息的订阅者的回调函数。这样比起让所有消息订阅者去实现一个 onEvent(BaseEvent event)的方法, 实际上是避免了一个多路分配的问题。

总结

对于一些类库在spring中使用,这种方法实际上是一种通用的模式,实现某个接口或者编写某个注解,然后通过ApplicationContext来获取对应的bean,之后进行某些注册或者组装操作。这样的话,可以让业务的代码,和框架的代码做到一定程度的关注点分离。

spring集成guava的event bus的更多相关文章

  1. guava cache与spring集成

    缓存的背景 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间.在cpu进行计算的时候, 首先是读取寄存器,然后内存,再是硬盘.由 ...

  2. Azure Event Bus 技术研究系列1-Event Hub入门篇

    前两个系列研究了Azure IoT Hub和Azure Messaging.最近准备继续研究Azure Event Bus,即Azure的事件中心.首先, Azure Event Hub的官方介绍: ...

  3. springboot集成Guava缓存

    很久没有写博客了,这段时间一直忙于看论文,写论文,简直头大,感觉还是做项目比较舒服,呵呵,闲话不多说,今天学习了下Guava缓存,这跟Redis类似的,但是适用的场景不一样,学习下吧.今天我们主要是s ...

  4. CXF框架介绍及Spring集成

    1.CXF框架概念介绍 Apache CXF 是一个开源的 WebService 框架,CXF可以用来构建和开发 WebService,这些服务可以支持多种协议,比如:SOAP.POST/HTTP.H ...

  5. Spring集成GuavaCache实现本地缓存

    Spring集成GuavaCache实现本地缓存: 一.SimpleCacheManager集成GuavaCache 1 package com.bwdz.sp.comm.util.test; 2 3 ...

  6. 从零开始学 Java - Spring 集成 Memcached 缓存配置(二)

    Memcached 客户端选择 上一篇文章 从零开始学 Java - Spring 集成 Memcached 缓存配置(一)中我们讲到这篇要谈客户端的选择,在 Java 中一般常用的有三个: Memc ...

  7. 从零开始学 Java - Spring 集成 ActiveMQ 配置(一)

    你家小区下面有没有快递柜 近两年来,我们收取快递的方式好像变了,变得我们其实并不需要见到快递小哥也能拿到自己的快递了.对,我说的就是类似快递柜.菜鸟驿站这类的代收点的出现,把我们原来快递小哥必须拿着快 ...

  8. 【转】Dubbo使用例子并且和Spring集成使用

    一.编写客户端和服务器端共用接口类1.登录接口类public interface LoginService {    public User login(String name, String psw ...

  9. 从零开始学 Java - Spring 集成 Memcached 缓存配置(一)

    硬盘和内存的作用是什么 硬盘的作用毫无疑问我们大家都清楚,不就是用来存储数据文件的么?如照片.视频.各种文档或等等,肯定也有你喜欢的某位岛国老师的动作片,这个时候无论我们电脑是否关机重启它们永远在那里 ...

随机推荐

  1. 大话设计模式(带目录完整版).pdf等

    点击进入百度网盘 大话设计模式(带目录完整版).pdf等 保存至网盘下载二维码举报 赞(0)| 评论 | 分享至 分享时间:2014-04-01 11:02 | 467次浏览 130次下载 81次保存 ...

  2. Swift2.0新特性

    随着刚刚结束的 WWDC 2015 苹果发布了一系列更新,这其中就包括了令人振奋的 Swift 2.0. 这是对之前语言特性的一次大幅的更新,加入了很多实用和方便的元素,下面我们就一起来看看这次更新都 ...

  3. Hbase案例分析(一)

    Hbase应用场景: 1 随机读或者写 2 大数据上的高并发操作,比如每秒对PB级数据进行上千次操作.(查询,删除等操作) 3 读写均是非常简单的操作,比如没有join操作 Hbase Schema设 ...

  4. Painting The Wall 期望DP Codeforces 398_B

    B. Painting The Wall time limit per test 1 second memory limit per test 256 megabytes input standard ...

  5. Gartner 如何看 RASP 和 WAF?

    在这个计算机网络飞速发展的网络时代里,新兴的网络威胁正在不断「侵蚀」着的应用程序和核心数据的安全,各种繁杂的防护手段也随之接踵而来.众所周知,Gartner 是全球最具权威的 IT 研究与顾问咨询公司 ...

  6. Colored Sticks

    poj2513:http://poj.org/problem?id=2513 题意:就是求一个欧拉回路. 题解:本题是判断欧拉通路是否存在,但是如果是用map的话就会超时,这里采用了trie树,有发现 ...

  7. Cxf + Spring3.0 入门开发WebService

    转自原文地址:http://sunny.blog.51cto.com/182601/625540/ 由于公司业务需求, 需要使用WebService技术对外提供服务,以前没有做过类似的项目,在网上搜寻 ...

  8. [topcoder]TopographicalImage

    BFS.这里用了queue,以及在数据结构里存了上一个的高度.也可以递归调用完成BFS,在调用之前做判断:http://community.topcoder.com/stat?c=problem_so ...

  9. 【HDOJ】2853 Assignment

    最小费用最大流可解最优解.至于dif如何解,可以把w扩大100倍,如果mission编号和排列P相等则对w+1,然后建立网络流.对结果取模100可以得到没有改变mission的company数目,用c ...

  10. mysql 限制并发select patch

    限制并发select的patch,代码量很少,主要是为了学习mysql的源码,yy一下. 增加两个全局控制变量: thread_limit_min thread_limit_max 增加一个条件变量: ...