EventListener原理

目录

流程

容器的刷新流程如下:

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中。
    原文作者:arnold
    原文地址: https://segmentfault.com/a/1190000015975224
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞