EventListener原理

arnold發表於2018-08-12

目錄

流程

容器的重新整理流程如下:

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }
      finally {
         // Reset common introspection caches in Spring`s core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

其中與EventListener有關聯的步驟

  • initApplicationEventMulticaster(); 初始化事件多播器
  • registerListeners(); 註冊Listener到多播器
  • finishBeanFactoryInitialization(beanFactory); 涉及將@EventListener轉為普通Listener
  • finishRefresh(); 釋出容器重新整理完成事件ContextRefreshedEvent

initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //找applicationEventMulticaster的元件
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
     this.applicationEventMulticaster =
           beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
     if (logger.isDebugEnabled()) {
        logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
     }
   }
   else {
     //沒有就建立一個
     this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
     //註冊到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 + "]");
     }
   }
}

registerListeners()

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 (earlyEventsToProcess != null) {
     for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
     }
   }
}

finishRefresh()

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.
   LiveBeansView.registerApplicationContext(this);
}

publishEvent() 釋出事件,我們也可以手動呼叫容器的publishEvent() 方法來發布事件

ApplicationContext.publishEvent(new MyEvent("test"));

publishEvent()

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   // 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);
     }
   }
}

@EventListener處理

原理:通過EventListenerMethodProcessor來處理@Eventlstener

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware 

EventListenerMethodProcessor 是一個 SmartInitializingSingleton。

SmartInitializingSingleton什麼時候執行呢?

在Refresh()

​ -> finishBeanFactoryInitialization(beanFactory);

​ -> DefaultListableBeanFactory#preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
     RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
     if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
           Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
           if (bean instanceof FactoryBean) {
              final FactoryBean<?> factory = (FactoryBean<?>) bean;
              boolean isEagerInit;
              if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                           ((SmartFactoryBean<?>) factory)::isEagerInit,
                      getAccessControlContext());
              }
              else {
                isEagerInit = (factory instanceof SmartFactoryBean &&
                      ((SmartFactoryBean<?>) factory).isEagerInit());
              }
              if (isEagerInit) {
                getBean(beanName);
              }
           }
        }
        else {
            // 建立bean
           getBean(beanName);
        }
     }
   }

   // Trigger post-initialization callback for all applicable beans...
   for (String beanName : beanNames) {
     Object singletonInstance = getSingleton(beanName);
     if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
           AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
              smartSingleton.afterSingletonsInstantiated();
              return null;
           }, getAccessControlContext());
        }
        else {
           smartSingleton.afterSingletonsInstantiated();
        }
     }
   }
}

preInstantiateSingletons 前半部分主要是遍歷beanNames 建立Bean。建立完bean後判斷各bean是不是SmartInitializingSingleton,如果是則執行 smartSingleton.afterSingletonsInstantiated()方法。

//org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated
public void afterSingletonsInstantiated() {
   List<EventListenerFactory> factories = getEventListenerFactories();
   ConfigurableApplicationContext context = getApplicationContext();
   String[] beanNames = context.getBeanNamesForType(Object.class);
   for (String beanName : beanNames) {
      if (!ScopedProxyUtils.isScopedTarget(beanName)) {
         Class<?> type = null;
         try {
            type = AutoProxyUtils.determineTargetClass(context.getBeanFactory(), beanName);
         }
         if (type != null) {
            if (ScopedObject.class.isAssignableFrom(type)) {
               try {
                  Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                        context.getBeanFactory(), ScopedProxyUtils.getTargetBeanName(beanName));
                  if (targetClass != null) {
                     type = targetClass;
                  }
               }
            }
            try {
                //處理bean
               processBean(factories, beanName, type);
            }
         }
      }
   }
}
protected void processBean(
     final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
 
   //沒有註解的class
   if (!this.nonAnnotatedClasses.contains(targetType)) {
     Map<Method, EventListener> annotatedMethods = null;
     try {
         //查詢被註解EventListener的方法
        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 = getApplicationContext();
        for (Method method : annotatedMethods.keySet()) {
           for (EventListenerFactory factory : factories) {
              if (factory.supportsMethod(method)) {
                Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
               //建立applicationListener,通過Adapter將註解形式的listener轉換為普通的listener
                ApplicationListener<?> applicationListener =
                      factory.createApplicationListener(beanName, targetType, methodToUse);
                if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                   ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                }
               //新增listner到applicationContext
                context.addApplicationListener(applicationListener);
                break;
              }
           }
        }
        if (logger.isDebugEnabled()) {
           logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean `" +
                beanName + "`: " + annotatedMethods);
        }
     }
   }
}
  • 查詢類中標註@EventListener的方法
  • EventListenerFactory.createApplicationListener(beanName, targetType, methodToUse) 構造listener
  • 新增listener到Context中

    • 如果有applicationEventMulticaster,新增到ApplicationContext.applicationEventMulticaster中
    • 如果沒有applicationEventMulticaster,新增到ApplicationContext.applicationListeners中。