美文网首页spring
spring源码事件监听

spring源码事件监听

作者: 念䋛 | 来源:发表于2022-07-07 20:01 被阅读0次

spring的事件监听机制,主要利用了监听者设计模式,那如何spring自带的事件和自定义的事件是如何触发监听器的,通过源码分析
最主要的对象是事件多播器AbstractApplicationEventMulticaster,默认的情况下使用的是SimpleApplicationEventMulticaster
1.多播器的初始化
org.springframework.context.support.AbstractApplicationContext的refresh方法是spring最重要的方法,其中的两个方法处理多播器
// Initialize event multicaster for this context. 初始化multicaster
initApplicationEventMulticaster();
// Check for listener beans and register them. 注册监听
registerListeners();
(1)initApplicationEventMulticaster

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断beanFactory里是否定义了bean名称为applicationEventMulticaster   
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {
//赋值applicationEventMulticaster 后续触发的时候会使用,初始化SimpleApplicationEventMulticaster的多播器
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//将SimpleApplicationEventMulticaster实例放到ioc容器中
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
               "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
   }
}

在没有自定义多播器的情况下,将SimpleApplicationEventMulticaster放到ioc容器中
(2)registerListeners 注册监听器

protected void registerListeners() {
   //注册系统的监听器
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

//从容器中获取监听器监听器,这里就包含了自定义的监听器,也包含了springboot监听和第三方的监听器
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }
//收集的监听器都存放defaultRetriever成员遍历里
   // Publish early application events now that we finally have a multicaster...
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

首先收集spring自带的监听,在收集第三方的监听器,这里包含了自定义,springboot和第三方组件的监听器,这里要注意的是listenerBeanNames 只是获取了bean的名称,并不会初始化bean,在后续的finishBeanFactoryInitialization方法初始化bean
2.收集监听器
上面只是说到了把监听器的名称收集起来,后续监听器的执行是需要监听实例执行的
finishBeanFactoryInitialization是如何收集监听器实例的
ApplicationListenerDetector实现了bean的后置处理器BeanPostProcessor
postProcessAfterInitialization方法

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
//bean是否实现了ApplicationListener接口
   if (bean instanceof ApplicationListener) {
      // potentially not detected as a listener by getBeanNamesForType retrieval
//关注postProcessMergedBeanDefinition方法中singletonNames如何赋值
      Boolean flag = this.singletonNames.get(beanName);
      if (Boolean.TRUE.equals(flag)) {
         // singleton bean (top-level or inner): register on the fly
//将bean收集起来
         this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
      }
      else if (Boolean.FALSE.equals(flag)) {
         if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
            // inner bean with other scope - can't reliably process events
            logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                  "but is not reachable for event multicasting by its containing ApplicationContext " +
                  "because it does not have singleton scope. Only top-level listener beans are allowed " +
                  "to be of non-singleton scope.");
         }
         this.singletonNames.remove(beanName);
      }
   }
   return bean;
}
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
   Assert.notNull(listener, "ApplicationListener must not be null");
   if (this.applicationEventMulticaster != null) {
//放到多播器中
      this.applicationEventMulticaster.addApplicationListener(listener);
   }
//放到applicationListeners
   this.applicationListeners.add(listener);
}

3.事件的执行
调用publishEvent方法,这里只关注主分支,调用multicastEvent方法

@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);
      }
   }
}

自定义事件调用的时候都是使用
applicationContext.publishEvent(event); applicationContext可以从容器中获取
4.各个事件执行时机
(1)上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
(2)上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
(3)上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
(4)上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
(5)请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。

相关文章

  • Spring源码探究:事件机制

    结合Spring源码分析Spring事件机制 问题 问题描述:项目中配置事件监听,监听当容器加载完成之后,做一些初...

  • Spring 源码 - 事件监听

    Spring中对事件的监听及处理是基于JDK的监听器实现的。在理解JDK的监听者实现之后,看这部分相关的源码会很清...

  • spring源码事件监听

    spring的事件监听机制,主要利用了监听者设计模式,那如何spring自带的事件和自定义的事件是如何触发监听器的...

  • 下单流程解耦新方案-你知道Spring事件监听机制吗

    一、Spring事件监听介绍 Spring对事件监听是通过事件类型、事件类型监听和事件发布器3个部分来完成的 上面...

  • Spring事件源码解析

    Spring事件监听源码分析 众所周知,在Spring中集成了内部的消息分发机制,可以在代码中使用注解@Event...

  • Spring事件监听源码解析

    大家对ApplicationListener应该不会陌生,但是大家是否了解Spring事件监听机制是怎么实现的呢?...

  • Spring事件监听--源码总结

    Spring事件监听 1.举例 (1)定义监听器监听的对象BaseFetchDataEvent (2)创建一个测试...

  • 浅谈Spring事件监听

    浅谈Spring事件监听在谈Spring的事件监听之前,让我们先了解一下Spring容器,什么是Applicati...

  • Spring源码阅读----Spring事件监听机制

    概述 经过IoC的解析,我们需要将注意力再拉回到refresh方法中。我们还有这几个方法还没解析完: 这里继续,先...

  • Spring 应用启动事件

    监听Spring boot应用的事件只需实现ApplicationListener接口来监听对应事件. 有些事件实...

网友评论

    本文标题:spring源码事件监听

    本文链接:https://www.haomeiwen.com/subject/oxwpbrtx.html