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

概述

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
// 注解注入该事件总线对象 :
// @Autowired
// EventBus eventBus;
// 然后使用它发布事件 : 
 eventBus.post("hello");

你可能感兴趣的:(Spring,Boot)