pre
Spring5源码 - 10 Spring事件监听机制_应用篇
说了应用,那我们来看下Spring的源码是如何实现这种事件监听机制的吧
事件监听机制的实现原理[观察者模式]
其实就是观察者模式
事件 ApplicationEvent
事件监听者 ApplicationEvent
相当于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑
事件发布者 ApplicationEventMulticaster (多播器)
相当于观察者模式中的被观察者/主题, 负责通知观察者 对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器
工作流程
Spring事件机制是观察者模式的一种实现,但是除了发布者和监听者者两个角色之外,还有一个EventMultiCaster的角色负责把事件转发给监听者。
AnnotationConfigApplicationContext#publishEvent(ApplicationEvent event)将事件发送给了EventMultiCaster, 而后由EventMultiCaster注册着所有的Listener,然后根据事件类型决定转发给那个Listener。
源码解析
debug走起,
Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了事件体系的搭建。
AbstractApplicationContext拥有一个applicationEventMulticaster成员变量,applicationEventMulticaster提供了容器监听器的注册表。
还是进入到refresh方法中
refresh() -----> 直接看 initApplicationEventMulticaster() -----------> registerListeners() ---------> finishRefresh() 进入 ----> publishEvent(new ContextRefreshedEvent(this))
初始化事件多播器 initApplicationEventMulticaster()
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //判断IOC容器中包含applicationEventMulticaster 事件多播器的Bean的name if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { /创建一个applicationEventMulticaster的bean放在IOC 容器中,bean的name 为applicationEventMulticaster this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { //容器中不包含一个beanName 为applicationEventMulticaster的多播器组件 //创建一个SimpleApplicationEventMulticaster 多播器 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 + "]"); } } }
一句话概括:我们可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster就可以了,Spring会通过 反射的机制将其注册成容器的事件广播器,如果没有找到配置的外部事件广播器,Spring默认使用 SimpleApplicationEventMulticaster作为事件广播器
注册事件到多播器中 registerListeners()
protected void registerListeners() { //去容器中把applicationListener 捞取出来注册到多播器上去(系统的) for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } //开发人员实现了ApplicationListener 的组件 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } //在这里之前,我们早期想发布的事件 由于没有多播器没有发布,在这里我们总算有了自己的多播器,可以在这里发布早期堆积的事件了. (早起发布事件,会自动发布,无需调用pubilish) Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
一句话概括 : Spring根据反射机制,使用ListableBeanFactory的getBeansOfType方法,从BeanDefinitionRegistry中找出所有实现 org.springframework.context.ApplicationListener的Bean,将它们注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。
事件发布publishEvent(默认同步)
org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Obj
进入 org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //获取到所有的监听器 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { //看spring 容器中是否支持线程池 异步发送事件 Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { //同步发送事件 invokeListener(listener, event); } } }
支持异步,默认同步 。
遍历注册的每个监听器,并启动来调用每个监听器的onApplicationEvent方法。由于SimpleApplicationEventMulticaster的taskExecutor的实现类是SyncTaskExecutor,因此,事件监听器对事件的处理,是同步进行的。
'
来看看
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { //调用对于listener的onApplicationEvent事件 listener.onApplicationEvent(event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || matchesClassCastMessage(msg, event.getClass())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for // -> let's suppress the exception and just log a debug message. Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
就是调用 listener.onApplicationEvent(event);