Spring容器的事件机制

一.概述

Spring容器暴漏了很多扩展点给框架的使用者,让框架的使用者能够干涉一些容器内部的事情,也让框架的使用能够感知到容器内部发生了什么事情,比如Spring容器在初始化完后,就会广播一个容器初始化完成的事件,然后事件的监听者监听到这个事件后做相应的事情,这也是Spring容器的一个非常有用的扩展点。

二.事件相关的类图

Spring事件机制相关的类图

上面这张类图就是Spring事件机制涉及到的一些核心类图。关于事件机制核心的接口有两个ApplicationEventMulticaster和ApplicationListener,前者是事件的广播中心接口,主要负责事件的广播和监听者的注册,后者是事件监听接口,还有一个事件对象ApplicationEvent,定义事件相关的属性,比如事件的类型,事件关联的数据,不过Spring中并没有定义相关的事件类型,不同的事件对应不同的类,比如ContextRefreshedEvent,表示Spring容器上下文初始化结束了。

其实事件这个概念在我们日常的开发中经常会被用到,很多人喜欢设计一个事件模块,要是让你去设计一个事件模块的话,需要考虑三个点,事件本身的定义,包括事件的类型以及事件所包含的数据,其次,需要定义事件的广播机制,一般有同步和异步,最后当然就是事件监听者的定义了,在监听者内部定义如何响应各自感兴趣的事件。

三.Spring事件机制的巧妙使用

Spring容器在初始化完成后,会发广播一个容器初始化OK的事件出来,我们可以在每个bean注册一个监听上下文刷新成功的事件,等上下文刷新成功了,我们在用这个bean去做一些其他事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class XXBean implements InitializingBean, ApplicationContextAware
    // 把Spring容器注入到这个beanpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof AbstractApplicationContext) {
            AbstractApplicationContext apc = (AbstractApplicationContext)applicationContext;
            // 注册新listener
            apc.addListener(new XXXApplicationListener());
        }
    }

    private final class XXXApplicationListener implements ApplicationListener {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof ContextRefreshedEvent) {
                // 这时候这个bean已经在Spring容器中初始化OK了
                XXBean.this.xxx.xxx // 使用初始化好的bean中的相关属性做一些事情
            }
        }
    }
}