您的位置:首页 > 编程语言 > Java开发

在Spring应用中以很“Spring”的方式使用Google Guava EventBus

2018-01-23 19:20 796 查看

概述

由Google提供的Guava EventBus是一个很不错的进程内事件总线机制。在非Spring应用中,使用 Guava EventBus是可以的,但各种组件,比如事件总线,事件监听器都是通过java new关键字创建出来的。这种开发人员自己管理对象生命周期的方式,在Spring应用中,就显得很不“Spring”,因为我们知道,Spring应用一个很大的特点就在于所有对象实例都尽量由Spring IoC容器来管理。本文先介绍一下非Spring应用中Guava EventBus一般的使用方式,然后再切换到Spring应用的情景,看看如何以很“Spring”的方式使用Guava EventBus。

非Spring应用中使用Guava EventBus

事件总线的定义

// 使用Java new关键字创建事件总线对象
EventBus eventBus = new EventBus();


定义事件消费者逻辑

定义事件消费者逻辑其实是利用Guava的注解@Subscribe指定当某个事件发生时执行所制定的逻辑,如下所示 :

class StringEventListener{

// 当所注册到的事件总线上发生String消息时,会在控制台上输出相应的消息
@Subscribe
public void listener(String event) {
System.out.println("receive msg:"+event);
}
}


注册事件消费者逻辑到事件总线

注册事件消费者逻辑到事件总线其实是告诉事件总线,当某某事件发生时,你要去执行我告诉你的逻辑。比如下面的例子,就是告诉事件总线对象eventBus,一旦发生String事件,你要调用方法事件监听器对象stringEventListener的方法listener。

// 注意 : 这里使用Java new关键字创建事件监听器对象
StringEventListener stringEventListener=new StringEventListener();
eventBus.register(stringEventListener);


事件生产者逻辑

下面的代码片段演示了消息生产者如何发布一个String消息的,该消息会触发上面事件监听器对象stringEventListener的方法listener的执行。

// 在开发人员需要发布事件的地方,开发人员通过某种方式拿到eventBus对象,通常可能是利用参数传递,
// 或者全局变量方式得到,然后发布事件
eventBus.post("hello");


Spring应用中使用Guava EventBus

事件总线的定义

// 该例子使用Spring注解@Configuration+@Bean的方式定义了一个事件总线bean,该bean最终的创建虽然使用了Java
// 关键字new,但整个bean的生命周期管理都托管给了Spring IoC容器,这是很“Spring”的应用方式,避免了开发人员自己
// 负责事件总线对象的生命周期管理
@Configuration
public class EventBusConfig {

//定义事件总线bean
@Bean
public EventBus eventBus() {
return new EventBus();
}
}


定义事件消费者逻辑

定义事件消费者逻辑其实是利用Guava的注解@Subscribe指定当某个事件发生时执行所制定的逻辑,如下所示 :

注意该例子跟非Spring应用中使用Guava EventBus时定义事件消费者逻辑的方式的区别:这里使用了Spring的注解@Component,该注解的作用是让Spring把该类作为一个bean定义注册到容器。

这种方式跟非Spring应用中使用Guava EventBus时定义事件消费者逻辑的方式区别的根本在于:开发人员不是自己在管理事件消费者对象的生命周期,而是交由Spring IoC容器来管理。

@Component
class StringEventListener{ // 当所注册到的事件总线上发生String消息时,会在控制台上输出相应的消息 @Subscribe public void listener(String event) { System.out.println("receive msg:"+event); } }


注册事件消费者逻辑到事件总线

该方式和非Spring应用中注册事件消费者逻辑到事件总线的方式也有很大不同,这里通过注解@Component定义了一个bean,并且他实现了Spring的接口BeanPostProcessor。利用这种方式,Spring IoC首先会在容器中定义了一个bean eventSubscribeBeanPostProcessor,然后在容器实例化其他每个bean时,会对该bean调用eventSubscribeBeanPostProcessor bean的方法postProcessAfterInitialization(),这样,我们就有一个机会来检测每个bean是否是一个Guava @Subscribe定义的事件监听器bean,如果是,我们就可将该bean注册到事件总线bean eventBus上。

@Component
public class EventSubscribeBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}

//对于每个容器执行了初始化的 bean,如果这个 bean 的某个方法注解了@Subscribe,则将该 bean 注册到事件总线
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// for each method in the bean
Method[] methods = bean.getClass().getMethods();
for (Method method : methods) {
// check the annotations on that method
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
// if it contains the Subscribe annotation
if (annotation.annotationType().equals(Subscribe.class)) {
// 如果这是一个Guava @Subscribe注解的事件监听器方法,说明所在bean实例
// 对应一个Guava事件监听器类,将该bean实例注册到Guava事件总线
eventBus.register(bean);
return bean;
}
}
}

return bean;
}

// 事件总线bean由Spring IoC容器负责创建,这里只需要通过@Autowired注解注入该bean即可使用事件总线
@Autowired
EventBus eventBus;
}


事件生产者逻辑

// 在开发人员需要发布事件的地方,开发人员可以通过很“Spring”的方式拿到eventBus对象,比如通常是利用@Autowired
// 注解注入该事件总线对象,然后使用它发布事件
eventBus.post("hello");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: