文章

spring源码分析

Spring Event

ApplicationEventMulticaster事件多播器的创建

  1. 从Spring refresh()进入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
           StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            ...
              // Initialize event multicaster for this context.
              initApplicationEventMulticaster();
            ...
              // Check for listener beans and register them.
              registerListeners();
            ...
           }
    
  2. 看看有没有”applicationEventMulticaster“bean,没有则new一个SimpleApplicationEventMulticaster

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
     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.isTraceEnabled()) {
              logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
           }
        }
        else {
           this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
           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() + "]");
           }
        }
     }
    

ApplicationListener监听器注册

  1. AbstractApplicationEventMulticaster中维护 一堆 私有类CachedListenerRetriever和 一个 DefaultListenerRetriever

    1
    2
    
       final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
       private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
    
    1. CachedListenerRetriever

      1
      2
      3
      4
      
      @Nullable
      public volatile Set<ApplicationListener<?>> applicationListeners;
      @Nullable
      public volatile Set<String> applicationListenerBeans;
      
  2. 上面已经初始化了从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    protected void registerListeners() {
       // Register statically specified listeners first.
       for (ApplicationListener<?> listener : getApplicationListeners()) {
          getApplicationEventMulticaster().addApplicationListener(listener);
       }
       
       // Do not initialize FactoryBeans here: We need to leave all regular beans
       // uninitialized to let post-processors apply to them!
       String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
       for (String listenerBeanName : listenerBeanNames) {
          getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
       }
       
       // 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);
          }
       }
    }
    
  3. 之后只要通过multicaster广播的事件,会循环3.1的set,于是各个ApplicationListener就可以监听到事件了

  4. 创建Listener的方式

    1. 实现ApplicationListener接口

    2. 使用@EventListener注解

    3. 1
      2
      
       public class EventListenerMethodProcessor
             implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
      

      当IoC容器完成所有单实例Bean的初始化工作后,触发afterSingletonsInstantiated()方法执行,是在DefaultListableBeanFactory#preInstantiateSingletons()方法中最后执行

    4. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      
       @Override
       public void afterSingletonsInstantiated() {
          ConfigurableListableBeanFactory beanFactory = this.beanFactory;
          Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
          String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
          for (String beanName : beanNames) {
             if (!ScopedProxyUtils.isScopedTarget(beanName)) {
                Class<?> type = null;
                try {
                   type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
                }
                catch (Throwable ex) {
                   // An unresolvable bean type, probably from a lazy bean - let's ignore it.
                   if (logger.isDebugEnabled()) {
                      logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
                   }
                }
                if (type != null) {
                   if (ScopedObject.class.isAssignableFrom(type)) {
                      try {
                         Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                               beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
                         if (targetClass != null) {
                            type = targetClass;
                         }
                      }
                      catch (Throwable ex) {
                         // An invalid scoped proxy arrangement - let's ignore it.
                         if (logger.isDebugEnabled()) {
                            logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
                         }
                      }
                   }
                   try {
                      processBean(beanName, type);
                   }
                   catch (Throwable ex) {
                      throw new BeanInitializationException("Failed to process @EventListener " +
                            "annotation on bean with name '" + beanName + "'", ex);
                   }
                }
             }
          }
       }
      
      1. 查找Class里有被 @EventListener注解的方法,存储到Map<Method, EventListener> annotatedMethods中;
      2. 然后遍历Map,对每个@EventListener注解方法,使用EventListenerFactory工厂模式创建一个ApplicationListener实例,默认这里是ApplicationListenerMethodAdapter类型;
      3. 最后使用context.addApplicationListener向Spring注册事件监听器;

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        
         private void processBean(final String beanName, final Class<?> targetType) {
            if (!this.nonAnnotatedClasses.contains(targetType) &&
                  AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
                  !isSpringContainerClass(targetType)) {
                    
               Map<Method, EventListener> annotatedMethods = null;
               try {
                  annotatedMethods = MethodIntrospector.selectMethods(targetType,
                        (MethodIntrospector.MetadataLookup<EventListener>) method ->
                              AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
               }
               catch (Throwable ex) {
                  // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
                  if (logger.isDebugEnabled()) {
                     logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
                  }
               }
                    
               if (CollectionUtils.isEmpty(annotatedMethods)) {
                  this.nonAnnotatedClasses.add(targetType);
                  if (logger.isTraceEnabled()) {
                     logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
                  }
               }
               else {
                  // Non-empty set of methods
                  ConfigurableApplicationContext context = this.applicationContext;
                  Assert.state(context != null, "No ApplicationContext set");
                  List<EventListenerFactory> factories = this.eventListenerFactories;
                  Assert.state(factories != null, "EventListenerFactory List not initialized");
                  for (Method method : annotatedMethods.keySet()) {
                     for (EventListenerFactory factory : factories) {
                        if (factory.supportsMethod(method)) {
                           Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                           //因为ApplicationListenerMethodAdapter内部持有@EventListener注解方法对应的Method
                           //以及该方法所处Bean的name信息。
                           //这样,就间接实现了将@EventListener方法包装成了ApplicationListener对象
                           ApplicationListener<?> applicationListener =
                                 factory.createApplicationListener(beanName, targetType, methodToUse);
                           if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                              ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                           }
                           context.addApplicationListener(applicationListener);
                           break;
                        }
                     }
                  }
                  if (logger.isDebugEnabled()) {
                     logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                           beanName + "': " + annotatedMethods);
                  }
               }
            }
         }
        

事件发布流程

  1. ContextRefreshedEvent,Bean创建的最后一步发送事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    protected void finishRefresh() {
       // Clear context-level resource caches (such as ASM metadata from scanning).
       clearResourceCaches();
       
       // Initialize lifecycle processor for this context.
       initLifecycleProcessor();
       
       // Propagate refresh to lifecycle processor first.
       getLifecycleProcessor().onRefresh();
       
       // Publish the final event.
       publishEvent(new ContextRefreshedEvent(this));
       
       // Participate in LiveBeansView MBean, if active.
       if (!NativeDetector.inNativeImage()) {
          LiveBeansView.registerApplicationContext(this);
       }
    }
    
  2. 将给定事件发布给所有监听器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
       Assert.notNull(event, "Event must not be null");
       
       // Decorate event as an ApplicationEvent if necessary
       ApplicationEvent applicationEvent;
       if (event instanceof ApplicationEvent) {
          applicationEvent = (ApplicationEvent) event;
       }
       else {
          applicationEvent = new PayloadApplicationEvent<>(this, event);
          if (eventType == null) {
             eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
          }
       }
       
       // Multicast right now if possible - or lazily once the multicaster is initialized
       if (this.earlyApplicationEvents != null) {
          this.earlyApplicationEvents.add(applicationEvent);
       }
       else {
          getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
       }
       
       // Publish event via parent context as well...
       if (this.parent != null) {
          if (this.parent instanceof AbstractApplicationContext) {
             ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
          }
          else {
             this.parent.publishEvent(event);
          }
       }
    }
    
  3. multicast派发事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
       ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
       //如果有Executor,可以支持异步派发
       Executor executor = getTaskExecutor();
       for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          if (executor != null) {
             executor.execute(() -> invokeListener(listener, event));
          }
          else {
             invokeListener(listener, event);
          }
       }
    }
    
  4. 获取监听器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
     // 根据ListenerCacheKey获取的监听器(CachedListenerRetriever)集合
     protected Collection<ApplicationListener<?>> getApplicationListeners(
                 ApplicationEvent event, ResolvableType eventType) {
             // event来自Spring的ApplicationEventPublisher.publishEvent(Object event)
             // 如果发布的不是继承自ApplicationEvent,则包装成一个PayloadApplicationEvent(source为ApplicationContext,
             // playload为自定义的event类)
             Object source = event.getSource();
             Class<?> sourceType = (source != null ? source.getClass() : null);
             // 获取原来发布的object的类型作为sourceType
             // eventType可以为空,如果为空则
             ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
        
             // Potential new retriever to populate
             CachedListenerRetriever newRetriever = null;
        
             // Quick check for existing entry on ConcurrentHashMap
             // 第一次取肯定为null
             CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
             if (existingRetriever == null) {
                 // Caching a new ListenerRetriever if possible
                 // 往retrieverCache里放一个new CachedListenerRetriever()
                 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<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
                 if (result != null) {
                     return result;
                 }
                 // If result is null, the existing retriever is not fully populated yet by another thread.
                 // Proceed like caching wasn't possible for this current local attempt.
             }
        
             return retrieveApplicationListeners(eventType, sourceType, newRetriever);
         }
    
  5. 自定义事件发布ApplicationEventPublisher.publishEvent(event)

    运行发现自动装载的是AnnotationConfigServletWebServerApplicationContext,publishEvent实际调用的仍是AbstractApplicationContext的publishEvent(event, null),与上面一致

本文由作者按照 CC BY 4.0 进行授权