美文网首页
Spring之事件机制初始化流程

Spring之事件机制初始化流程

作者: Mr_1214 | 来源:发表于2018-12-13 11:53 被阅读19次

描述

在Spring之事件机制模型中我们了解了spring事件机制的模型以及工作流程,下面通过源码分析spring事件机制的初始化流程

在工作流程中,可以看到事件发布者ApplicationEventPublisher 发布事件是通过事件广播中心ApplicationEventMulticaster 将事件event通知到具体的事件监听器ApplicationListener 那么初始化流程应该有如下几步:

  1. 给事件发布者ApplicationEventPublisher 设置ApplicationEventMulticaster并初始化
  2. 注册事件监听器到事件ApplicationEventMulticaster
  3. 事件发布时,通过ApplicationEventMulticaster通知事件监听器。

初始化入口

// 类 AbstractApplicationContext
  public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //容器刷新前的处理方法
            prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //使用容器前beanFactory的前置处理方法
            prepareBeanFactory(beanFactory)
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                //在容器中执行bean工厂后置处理器
                // 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();

                //初始化容器的事件广播器
                initApplicationEventMulticaster();

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

                // 注册事件监听器到事件广播器中
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
            }
            catch (BeansException ex) {
                throw ex;
            }
        }
    }

ApplicaitonContext 继承事件发布者接口,在ApplicaitonContext的refresh方法中完成了事件机制初始化的流程,如下:

  1. 初始化发布者即容器的事件广播中心ApplicationEventMulticaster
    //初始化容器的事件广播器
    initApplicationEventMulticaster();
  1. 注册事件监听器到事件广播中心
        // 注册事件监听器到事件广播器中
        registerListeners();

initApplicationEventMulticaster

    /**
     * 初始化当前容器发布者持有的事件广播中心实例
     */
    protected void initApplicationEventMulticaster() {
        //获取beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        //判断beanFactory中是否存在事件广播中心bean实例
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            //存在时,beanFactory中的事件广播中心bean实例赋值给applicationEventMulticaster
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        }
        else {
            //不能存在,new 创建新的applicationEventMulticaster并赋值给applicationEventMulticaster
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            //将创建的新事件广播中心bean实例注册到单例bean注册中心
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        }
    }

initApplicationEventMulticaster 方法主要功能是创建事件广播中心实例,创建的方式:

  • beanFactory 已经存在实例 ,通过beanFactory获取已经存在的实例赋值给当前发布者
  • 不存在,通过new 关键字创建实例,赋值给发布者,并将当前实例注册到单例注册中心

registerListeners

    protected void registerListeners() {
        // 注册静态指定的事件监听器ApplicationListener到事件广播中心ApplicationEventMulticaster
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // 在beanFactory中查找ApplicationListener名称集合
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            //遍历名称并将当前名称的事件监听器注册到事件广播中心
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        //所有事件监听器添加完成后,遍历发布者(ApplicationEventPublisher-ApplicaitonContext)已经发布的事件集合,并将事件通知到给定的监听器
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                //通过事件广播中心ApplicationEventMulticaster,下发事件到具体的监听器ApplicationListener
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

registerListeners 方法主要完成将监听器注册到事件广播中心实例中,在initApplicationEventMulticaster创建了事件广播中心实例,但广播中心还没有持有任何监听器,这步主要完成监听器的注册,以便事件下发时,能找到对应的监听器。

spring 通过如下方式获取监听器,并注册的广播中心:

  1. 获取容器中静态设置的监听器注册
  2. 通过beanFactory中查找监听器注册

registerListeners 还完成了(下发在事件机制初始化完成前的发布事件)功能,ApplicaitonContext将事件机制未初始化完成前发布的事件保存在earlyApplicationEvents集合中,当前事件机制完成后统一下发到事件监听器。实现就是在registerListeners方法中,代码如下:

    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                //通过事件广播中心ApplicationEventMulticaster,下发事件到具体的监听器ApplicationListener
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }

ApplicaitonContext事件发布

//类 AbstractApplicationContext
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        //当事件机制未初始化完成前,将下发的事件保存在集合中,等待事件机制初始化完成后统一下发
        // 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);
            }
        }
    }

ApplicaitonContext继承事件发布者接口,具有了事件发布的功能,ApplicaitonContext事件发布完成如下操作:

  1. 事件机制未初始化完成,将事件保存到set集合。
  2. 事件机制初始化完成,调用事件广播器,发布事件
  3. 将事件透传到父级上下问环境ApplicaitonContext

事件机制初始化总结: ApplicaitonContext 的refresh方法调用完成后,就完成了整个事件机制的初始化工作,并将上下文中未下发到监听器的事件统一通过事件广播中心下发到事件监听器。

相关文章

网友评论

      本文标题:Spring之事件机制初始化流程

      本文链接:https://www.haomeiwen.com/subject/wmyuhqtx.html