Spring事件体系包括三个组件:事件,事件监听器,事件广播器。
事件:ApplicationEvent
事件监听器:ApplicationListener,对监听到的事件进行处理。
事件广播器:ApplicationEventMulticaster,将Springpublish的事件广播给所有的监听器。
Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了事件体系的搭建。
AbstractApplicationContext拥有一个applicationEventMulticaster成员变 量,applicationEventMulticaster提供了容器监听器的注册表。
AbstractApplicationContext在refresh()这个容器启动方法中搭建了事件的基础设施。
- try {
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors();
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors();
- // Initialize message source for this context.
- initMessageSource();
- // Initialize event multicaster for this context.
- initApplicationEventMulticaster();
- // Initialize other special beans in specific context subclasses.
- onRefresh();
- // Check for listener beans and register them.
- registerListeners();
- // Instantiate singletons this late to allow them to access the message source.
- beanFactory.preInstantiateSingletons();
- // Last step: publish corresponding event.
- publishEvent( new ContextRefreshedEvent( this));
- }
1、事件广播器的初始化:
- private void initApplicationEventMulticaster() throws BeansException {
- if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME )) {
- this.applicationEventMulticaster = (ApplicationEventMulticaster)
- getBean( APPLICATION_EVENT_MULTICASTER_BEAN_NAME ,
- ApplicationEventMulticaster.class );
- if (logger.isInfoEnabled()) {
- logger.info("Using ApplicationEventMulticaster ["
- + this. applicationEventMulticaster + "]" );
- }
- }
- else {
- this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();
- if (logger.isInfoEnabled()) {
- logger.info("Unable to locate ApplicationEventMulticaster with name '"+
- APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
- "': using default [" + this .applicationEventMulticaster + "]");
- }
- }
- }
用户可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster就可以了,Spring会通过 反射的机制将其注册成容器的事件广播器,如果没有找到配置的外部事件广播器,Spring自动使用 SimpleApplicationEventMulticaster作为事件广播器。
2、注册事件监听器
- private void registerListeners () throws BeansException {
- // Do not initialize FactoryBeans here: We need to leave all regular beans
- // uninitialized to let post-processors apply to them!
- Collection listeners = getBeansOfType(ApplicationListener.class,true,false).values();
- for (Iterator it = listeners.iterator(); it.hasNext();) {
- addListener((ApplicationListener) it.next());
- }
- }
- protected void addListener(ApplicationListener listener) {
- getApplicationEventMulticaster().addApplicationListener(listener);
- }
Spring根据反射机制,使用
ListableBeanFactory的
getBeansOfType方法,从BeanDefinitionRegistry中找出所有实现 org.springframework.context.ApplicationListener的Bean,将它们注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。
3、发布事件
- public void publishEvent(ApplicationEvent event) {
- Assert. notNull(event, "Event must not be null");
- if (logger .isDebugEnabled()) {
- logger .debug("Publishing event in context ["
- + getDisplayName() + "]: " + event);
- }
- getApplicationEventMulticaster(). multicastEvent(event);
- if (this .parent != null) {
- this .parent .publishEvent(event);
- }
- }
在AbstractApplicationContext的publishEvent方法中, Spring委托ApplicationEventMulticaster将事件通知给所有的事件监听器
4、Spring默认的事件广播器SimpleApplicationEventMulticaster
- public void multicastEvent( final ApplicationEvent event) {
- for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
- final ApplicationListener listener = (ApplicationListener) it.next();
- getTaskExecutor().execute( new Runnable() {
- public void run() {
- listener.onApplicationEvent(event);
- }
- });
- }
- }
遍历注册的每个监听器,并启动来调用每个监听器的onApplicationEvent方法。
由于SimpleApplicationEventMulticaster的taskExecutor的实现类是
SyncTaskExecutor,因此,事件监听器对事件的处理,是同步进行的。
从代码可以看出,applicationContext.publishEvent()方法,需要同步等待各个监听器处理完之后,才返回。
也就是说,Spring提供的事件机制,默认是同步的。如果想用异步的,可以自己实现ApplicationEventMulticaster接口,并在Spring容器中注册id为
applicationEventMulticaster的Bean。
例子:
spring配置:
Spring发布事件之后,所有注册的事件监听器,都会收到该事件,因此,事件监听器在处理事件时,需要先判断该事件是否是自己关心的。
例子:
- public class AsyncApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
- private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
- public void setTaskExecutor(TaskExecutor taskExecutor) {
- this.taskExecutor = (taskExecutor != null ? taskExecutor : new SimpleAsyncTaskExecutor());
- }
- protected TaskExecutor getTaskExecutor() {
- return this.taskExecutor;
- }
- @SuppressWarnings("unchecked")
- public void multicastEvent(final ApplicationEvent event) {
- for (Iterator<ApplicationListener> it = getApplicationListeners().iterator(); it.hasNext();) {
- final ApplicationListener listener = it.next();
- getTaskExecutor().execute(new Runnable() {
- public void run() {
- listener.onApplicationEvent(event);
- }
- });
- }
- }
- }
- <bean id="applicationEventMulticaster"
- class="com.alibaba.chj.event.AsyncApplicationEventMulticaster" />
Spring发布事件之后,所有注册的事件监听器,都会收到该事件,因此,事件监听器在处理事件时,需要先判断该事件是否是自己关心的。
Sping事件体系所使用的设计模式是:观察者模式。
ApplicationListener是观察者接口,接口中定义了onApplicationEvent方法,该方法的作用是对ApplicationEvent事件进行处理。