spring

spring源码事件监听

2022-07-07  本文已影响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)结束触发该事件。

上一篇 下一篇

猜你喜欢

热点阅读