Spring事件監聽機制
- 2019 年 10 月 5 日
- 筆記
前言
Spring中的事件機制其實就是設計模式中的觀察者模式,主要由以下角色構成:
- 事件
- 事件監聽器(監聽並處理事件)
- 事件發布者(發布事件)
首先看一下監聽器和發布者的介面定義
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); } public interface ApplicationEventPublisher { default void publishEvent(ApplicationEvent event) { publishEvent((Object) event); } void publishEvent(Object event); }
事件流轉流程
初始化事件廣播器
看一下這個方法AbstractApplicationContext.refresh,在IOC源碼解析那篇文章已經把這個方法分析完了,所以直接關注事件廣播器和事件發布相關的邏輯即可
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // 初始化事件廣播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // 發布事件 finishRefresh(); } catch (BeansException ex) { logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex); // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }
可以看到如果沒有自定義的事件廣播器,默認是使用SimpleApplicationEventMulticaster的
發布事件
發布事件是在bean的初始化之後的
protected void finishRefresh() { // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // 發布事件 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); } public void publishEvent(ApplicationEvent event) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } //1. 獲取到事件廣播器,發布事件 getApplicationEventMulticaster().multicastEvent(event); //2. 如果存在父容器,父容器也將發布事件 if (this.parent != null) { this.parent.publishEvent(event); } }
具體的發布邏輯在multicastEvent方法中
public void multicastEvent(final ApplicationEvent event) { //遍歷執行listener,getApplicationListeners調用AbstractApplicationEventMulticaster父類方法 for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
可以看到也沒啥特殊的,無非就是起個執行緒池去調用這些監聽器的方法
而監聽器的處理就看各個監聽器的具體實現了
