且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Spring中自定义事件原理

更新时间:2022-06-21 11:59:01

  1. Spring中所有的事件监听器实现ApplicationListener.onApplicationEvent(E event)方法
  2. Spring容器会在启动的过程中获取所有的监听器对象,并持有,当有事件被抛出时,就会轮询所有监听这个事件的监听器进行处理。

通过源码理解过程:

  protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
      ApplicationEvent applicationEvent;
      if (event instanceof ApplicationEvent) {
          applicationEvent = (ApplicationEvent) event;
      }
      else {
          //封装成applicationEvent
          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) {
          //监听器在注册到容器之前累积的事件,监听器注册完成之后会消耗掉这些事件,并将earlyApplicationEvents置空
          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);
          }
      }
  }

SimpleApplicationEventMulticaster事件广播器

  //广播事件
  public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
      ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
      for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          Executor executor = getTaskExecutor();
          if (executor != null) {//通过线程池处理
              executor.execute(() -> invokeListener(listener, event));
          }
          else {//在当前线程处理
              invokeListener(listener, event);
          }
      }
  }

  //处理事件
  private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
      //调用监听器的方法进行处理
      listener.onApplicationEvent(event);
  }
  1. 监听器的创建过程
    EventListenerMethodProcessor对象会在容器中的对象实例化完成后,会对有@EventListener注解的方法进行代理,并创建相应的监听器。

具体看EventListenerMethodProcessor.processBean()方法

protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {

    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()) {
                //轮询所有的EventListenerFactory
                for (EventListenerFactory factory : factories) {
                    //判断该监听器工厂是否支持该方法
                    if (factory.supportsMethod(method)) {
                        //创建一个代理对象
                        Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                        //用该工厂创建一个监听器
                        ApplicationListener<?> applicationListener =
                                factory.createApplicationListener(beanName, targetType, methodToUse);
                        //初始化监听器        
                        if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                            ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                        }
                        //把监听器放到context中。
                        context.addApplicationListener(applicationListener);
                        break;//监听器不能重复,避免多个监听器工厂都支持同一个事件处理方法(工厂是排过序的)
                    }
                }
            }
            ......
        }
    }
}