@EventListener

简介

@EventListener,一个可以把Method标记为处理应用事件ApplicationEvent处理器ApplicationListener的注解。

用法

声明

声明一个public的方法并指定要处理的ApplicationEvent,如ApplicationReadyEvent,同时使用@EventListener标记:

package org.ifinal.finalframework.example;

@Slf4j
@SpringBootApplication
public class FinalApplication {

   public static void main(final String[] args) {

      SpringApplication application = new SpringApplication(FinalApplication.class);
      application.run(args);

   }

   @EventListener
   public void onReady(final ApplicationReadyEvent readyEvent) {
      logger.info("onReady from @EventListener");
   }

}

尝试

--2021-01-15 15:19:21.157 - INFO 6522 --- [           main] o.i.f.example.FinalApplication           : [                                      ] : onReady from @EventListener

原理

注册

在容器的启动过程中,会注册以下两个Bean:

以下为注册的关键代码块AnnotationConfigUtils.registerAnnotationConfigProcessors()

package org.springframework.context.annotation;

public abstract class AnnotationConfigUtils {

   /**
    * The bean name of the internally managed @EventListener annotation processor.
    */
   public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
           "org.springframework.context.event.internalEventListenerProcessor";

   /**
    * The bean name of the internally managed EventListenerFactory.
    */
   public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
           "org.springframework.context.event.internalEventListenerFactory";

   public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
           BeanDefinitionRegistry registry, @Nullable Object source) {

      if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
         RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
         def.setSource(source);
         beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
      }

      if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
         RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
         def.setSource(source);
         beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
      }
   }

}

DefaultEventListenerFactory

DefaultEventListenerFactoryEventListenerFactory的默认实现,EventListenerFactory接口定义了将@EventListener转化为ApplicationListener的策略方法。

package org.springframework.context.event;

public interface EventListenerFactory {

   boolean supportsMethod(Method method);

   ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method);

}

DefaultEventListenerFactory将所有标记有@EventListener注解的方法转化为ApplicationListenerMethodAdapter

package org.springframework.context.event;

public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {

   @Override
   public boolean supportsMethod(Method method) {
      return true;
   }

   @Override
   public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
      return new ApplicationListenerMethodAdapter(beanName, type, method);
   }

}

EventListenerMethodProcessor

EventListenerMethodProcessorBeanFactoryPostProcessor的实现之一,基类关系如下图所示:

classDiagram
    SmartInitializingSingleton <|-- EventListenerMethodProcessor
    BeanFactoryPostProcessor <|-- EventListenerMethodProcessor
    ApplicationContextAware <|-- EventListenerMethodProcessor
    
    class EventListenerMethodProcessor {
        +ConfigurableApplicationContext applicationContext
        +ConfigurableListableBeanFactory beanFactory
        +List<EventListenerFactory> eventListenerFactories
    }
    
    class BeanFactoryPostProcessor {
        
        + postProcessBeanFactory(ConfigurableListableBeanFactory)
    }
    
    class SmartInitializingSingleton {
        + afterSingletonsInstantiated()
    }
    
    class ApplicationContextAware {
        + setApplicationContext(ApplicationContext)
    }

postProcessBeanFactory()

postProcessBeanFactory回调中,获取到容器中所有EventListenerFactory实例,这里实际上是DefaultEventListenerFactory:

package org.springframework.context.event;

public class EventListenerMethodProcessor
        implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
      this.beanFactory = beanFactory;

      Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
      List<EventListenerFactory> factories = new ArrayList<>(beans.values());
      AnnotationAwareOrderComparator.sort(factories);
      this.eventListenerFactories = factories;
   }

}

afterSingletonsInstantiated()

afterSingletonsInstantiated()回调中,主要通过以下几个步骤,将一个标记有@EventListener的方法转化为ApplicationListener并注册到ConfigurableApplicationContext中。

String[]beanNames=beanFactory.getBeanNamesForType(Object.class);
annotatedMethods=MethodIntrospector.selectMethods(targetType,(MethodIntrospector.MetadataLookup<EventListener>)
        method->AnnotatedElementUtils.findMergedAnnotation(method,EventListener.class));
ApplicationListener<?> applicationListener=factory.createApplicationListener(beanName,targetType,methodToUse);
context.addApplicationListener(applicationListener);

至此,@EventListener注解的解析过程就结束了。

小结

本文通过分析EventListenerMethodProcessorDefaultEventListenerFactory的核心源码,了解了被@EventListener注解标记的方法是如何被解析成ApplicationListener 并注册到ConfigurableApplicationContext,以实现处理ApplicationEvent的原理:

  1. BeanFactoryPostProcessor后置处理器的postProcessBeanFactory()回调方法中,获取到所有EventListenerFactory实例
  2. SmartInitializingSingletonafterSingletonsInstantiated() 回调方法中,遍历所有bean,找出标记有@EventListener方法通过EventListenerFactory转化为ApplicationListener,然后添加到ConfigurableApplicationContext中。