事件监听机制是观察者模式的一种,Spring的事件监听机制有几个重要的顶层接口,分别是:
它们三哥们的关系可以用下面的图来概括
AbstractApplicationEventMulticaster维护了 源类型和事件类型 作为KEY 跟 监听器的关系,在下面 2.1 SimpleApplicationEventMulticaster有代码的实现解读。
目前就只有一个实现类SimpleApplicationEventMulticaster和一个抽象类AbstractApplicationEventMulticaster。
发布和广播事件,主要注意一下getApplicationListeners方法就行了,会根据事件类型和源类型找监听器。
@Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); } @Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }
getApplicationListeners方法就是根据Class>、ResolvableType两个对象作为一个缓存key,这个key与一堆监听器`ApplicationListener`做映射,也就是说通过Class>、ResolvableType两个对象可以找到监听器,在用法上可以从SimpleApplicationEventMuticaster的 multicastEvent 方法去看。
看看getApplicationListeners方法的代码实现
protected Collection> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); CachedListenerRetriever newRetriever = null; // 这个cacheKey就是ApplicationEvent,ResolvableType两个对象。 // 根据cacheKey找监听器,找不到就把cacheKey作为key,创建一个什么都么有的CachedListenerRetriever对象作为值缓存到retrieverCache中。 // 这里有一些细节我没搞明白,putIfAbsent总是返回null。 CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey); if (existingRetriever == null) { if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { newRetriever = new CachedListenerRetriever(); existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever); if (existingRetriever != null) { newRetriever = null; // no need to populate it in retrieveApplicationListeners } } } if (existingRetriever != null) { Collection > result = existingRetriever.getApplicationListeners(); if (result != null) { return result; } } // 假设上面cacheKey对应的值没有监听器,那这个方面就找 给定事件类型和源类型 的监听器。 return retrieveApplicationListeners(eventType, sourceType, newRetriever); } // 从默认的 defaultRetriever 和 我们注入的bean 中找监听器。 private Collection > retrieveApplicationListeners( ResolvableType eventType, @Nullable Class> sourceType, @Nullable CachedListenerRetriever retriever) { List > allListeners = new ArrayList<>(); Set > filteredListeners = (retriever != null ? new LinkedHashSet<>() : null); Set filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null); Set > listeners; Set listenerBeans; synchronized (this.defaultRetriever) { listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans); } // 从defaultRetriever中找监听器 // 这里的supportsEvent有点看不懂,不过只要理解通过事件类型和源类型判断监听器是否符合 事件要求就得了。 for (ApplicationListener> listener : listeners) { if (supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { filteredListeners.add(listener); } allListeners.add(listener); } } // 根据bean名字去找监听器 if (!listenerBeans.isEmpty()) { ConfigurableBeanFactory beanFactory = getBeanFactory(); for (String listenerBeanName : listenerBeans) { try { if (supportsEvent(beanFactory, listenerBeanName, eventType)) { ApplicationListener> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { if (beanFactory.isSingleton(listenerBeanName)) { filteredListeners.add(listener); } else { filteredListenerBeans.add(listenerBeanName); } } allListeners.add(listener); } } else { Object listener = beanFactory.getSingleton(listenerBeanName); if (retriever != null) { filteredListeners.remove(listener); } allListeners.remove(listener); } } catch (NoSuchBeanDefinitionException ex) { } } } // 把找到的监听器都放到CachedListenerRetriever中。 AnnotationAwareOrderComparator.sort(allListeners); if (retriever != null) { if (filteredListenerBeans.isEmpty()) { retriever.applicationListeners = new LinkedHashSet<>(allListeners); retriever.applicationListenerBeans = filteredListenerBeans; } else { retriever.applicationListeners = filteredListeners; retriever.applicationListenerBeans = filteredListenerBeans; } } return allListeners; }
主要是了解如何注册和自定义监听器就行了
通过META-INF/spring.factories注册监听器。
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.bootstrapRegistryInitializers = new ArrayList<>( getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 这里就是注册ApplicationListener的代码了,通过META-INF/spring.factories注册。 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
public class MyApplicationPreparedListener implements ApplicationListener{ @Override public void onApplicationEvent(ApplicationPreparedEvent event) { System.out.println("开始填充上下文。。。。"); } }
MATE-INF/spring.factories
org.springframework.context.ApplicationListener=sample.config.MyApplicationPreparedListener
SpringApplicationRunListeners管理了多个EventPublishingRunListener,EventPublishingRunListener里面包含了事件监听器模型#1.概述(重点)中描述的部分。
class SpringApplicationRunListeners { private final Log log; private final Listlisteners; private final ApplicationStartup applicationStartup; ... } public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; ... }
EventPublishingRunListener中定义了Spring整个启动过程中会触发的事件,下面对触发位置进行大概的描述,更具体的内容还有待研究。
在SpringApplication#run,事件ApplicationStartingEvent
在SpringApplication#prepareEnvironment,事件ApplicationEnvironmentPreparedEvent
在SpringApplication#prepareContext,事件ApplicationContextInitializedEvent
在SpringApplication#prepareContext,事件ApplicationPreparedEvent
在SpringApplication#run,事件ApplicationStartedEvent
在SpringApplication#run,事件ApplicationReadyEvent
在SpringApplication#handleRunFailure,事件ApplicationFailedEvent
我们也可以利用上面的事件,自己创建一个监听器,然后放到spring.factories,比如现在注册一个ApplicationPreparedEvent的监听器。
public class MyApplicationPreparedListener implements ApplicationListener{ @Override public void onApplicationEvent(ApplicationPreparedEvent event) { System.out.println("开始填充上下文。。。。"); } }
MATE-INF/spring.factories
org.springframework.context.ApplicationListener=sample.config.MyApplicationPreparedListener