蕲春做网站,呼和浩特网站推广,wordpress视频模板下载,东莞寮步华衍学校Guava的event busguava#xff0c; https://github.com/google/guava 是一个非常有名的Java类库#xff0c;提供了很多在日常开发中常用的集合、函数接口等。此外#xff0c;guava还提供了一个模块叫做event bus#xff0c;生产者往event bus上投递消息#xff0c;event b…Guava的event busguava https://github.com/google/guava 是一个非常有名的Java类库提供了很多在日常开发中常用的集合、函数接口等。此外guava还提供了一个模块叫做event bus生产者往event bus上投递消息event bus负责回调订阅了此类消息的回调函数实现了消息生产者和消费者之间的解耦和异步处理。以下是一个简单的例子public classSimpleListener {Subscribepublic voidtask(String s) {System.out.println(do task( s ));}}public classSimpleEventBusExample {public static voidmain(String[] args) {EventBus eventBus newEventBus();eventBus.register(newSimpleListener());System.out.println(Post Simple EventBus Example);eventBus.post(Simple EventBus Example);}}outputPost Simple EventBus Exampledo 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)DocumentedServicepublic interfaceEventSubscriber {}对于一个订阅者在类的接口上加上这个注解并且确定这个bean会在纳入spring的生命周期管理中。EventSubscriberpublic class SimpleSubscriber implementsHiDasSubscriber {AutowiredSomebean somebean;SubscribeAllowConcurrentEventspublicInteger logEventToDbAndUpdateStatus(String event) {System.out.println(receive a event:event);}}声明一个event bus的服务并且在初始化之后通过ApplicationContext的 getBeansWithAnnotation 的方法把所有的订阅者获取并且注册到event bus中。Servicepublic class EventBusService implementsInitializingBean{privateEventBus innerBus;InjectprivateApplicationContext appContext;public voidunRegister(Object eventListener){innerBus.unregister(eventListener);}public voidpostEvent(String event){innerBus.post(event);}public voidregister(Object eventListener){innerBus.register(eventListener);}Overridepublic void afterPropertiesSet() throwsException {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之后进行某些注册或者组装操作。这样的话可以让业务的代码和框架的代码做到一定程度的关注点分离。