Spring源码之九finishRefresh详解

公众号搜寻【程序员田同学】,专职程序员兼业余写手,生存不止于写代码

Spring IoC 的核心内容要收尾了,本文将对最初一个办法 finishRefresh 进行介绍,位于refresh 办法中的第九个地位。

本章理论是对公布订阅模式的一种补充,这是Spring在刷新事件实现后公布事件。

因为存在上下文关系,本文也会对 initApplicationEventMulticaster 办法、registerListeners 办法进行回顾。

咱们回到refresh 办法中。

@Override    public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // Prepare this context for refreshing.            //1、刷新前的筹备            prepareRefresh();            // Tell the subclass to refresh the internal bean factory.            //2、将会初始化 BeanFactory、加载 Bean、注册 Bean            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // Prepare the bean factory for use in this context.            //3、设置 BeanFactory 的类加载器,增加几个 BeanPostProcessor,手动注册几个非凡的 bean            prepareBeanFactory(beanFactory);            try {                //4、模板办法                // Allows post-processing of the bean factory in context subclasses.                postProcessBeanFactory(beanFactory);                // Invoke factory processors registered as beans in the context.                //执行BeanFactory后置处理器                invokeBeanFactoryPostProcessors(beanFactory);                // 5、Register bean processors that intercept bean creation.                //注册bean后置处理器                registerBeanPostProcessors(beanFactory);                // Initialize message source for this context.                //国际化                initMessageSource();                // Initialize event multicaster for this context.                //初始化事件播送器                initApplicationEventMulticaster();                // Initialize other special beans in specific context subclasses.                //6、模板办法--springboot实现了这个办法                onRefresh();                // Check for listener beans and register them.                //7、注册监听器                registerListeners();                // Instantiate all remaining (non-lazy-init) singletons.                //8、实现bean工厂的初始化**办法重要**********************************************                finishBeanFactoryInitialization(beanFactory);                //9、 Last step: publish corresponding event.                //实现上下文的刷新工作                finishRefresh();            }            catch (BeansException ex) {                if (logger.isWarnEnabled()) {                    logger.warn("Exception encountered during context initialization - " +                            "cancelling refresh attempt: " + ex);                }                // Destroy already created singletons to avoid dangling resources.                destroyBeans();                // Reset 'active' flag.                cancelRefresh(ex);                // Propagate exception to caller.                throw ex;            }            finally {                // Reset common introspection caches in Spring's core, since we                // might not ever need metadata for singleton beans anymore...                resetCommonCaches();            }        }    }

咱们首先晓得这个三个办法的作用:

initApplicationEventMulticaster():初始化利用的事件播送器

/**     * Initialize the ApplicationEventMulticaster.     * Uses SimpleApplicationEventMulticaster if none defined in the context.     * @see org.springframework.context.event.SimpleApplicationEventMulticaster     */    protected void initApplicationEventMulticaster() {        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        // 1.判断BeanFactory是否曾经存在事件播送器(固定应用beanName=applicationEventMulticaster)        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {            // 1.1 如果曾经存在,则将该bean赋值给applicationEventMulticaster            this.applicationEventMulticaster =                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);            if (logger.isTraceEnabled()) {                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");            }        }        else {            // 1.2 如果不存在,则应用SimpleApplicationEventMulticaster            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);            if (logger.isTraceEnabled()) {                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");            }        }    }

最终只做了一件事,初始化利用的事件播送器。(具体什么是事件播送器及其作用可见上上篇文章,具体就不在吃赘述了)

registerListeners():注册监听器。见上上篇文章

finishRefresh():实现上下文的刷新工作,本文重点

首先概览finishRefresh办法

    protected void finishRefresh() {        // Clear context-level resource caches (such as ASM metadata from scanning).        //革除资源缓存        clearResourceCaches();        // Initialize lifecycle processor for this context.        // // 1.为此上下文初始化生命周期处理器        initLifecycleProcessor();        // Propagate refresh to lifecycle processor first.        // 2.首先将刷新结束事件流传到生命周期处理器(触发isAutoStartup办法返回true的SmartLifecycle的start办法)        getLifecycleProcessor().onRefresh();        // Publish the final event.        // 3.推送上下文刷新结束事件到相应的监听器        publishEvent(new ContextRefreshedEvent(this));        // Participate in LiveBeansView MBean, if active.        LiveBeansView.registerApplicationContext(this);    }

1、2、3是重点内容

1.为此上下文初始化生命周期处理器

    protected void initLifecycleProcessor() {        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        // 1.判断BeanFactory是否曾经存在生命周期处理器(固定应用beanName=lifecycleProcessor)        if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {            this.lifecycleProcessor =                    beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);            if (logger.isTraceEnabled()) {                logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");            }        }        else {            // 1.2 如果不存在,则应用DefaultLifecycleProcessor            DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();            defaultProcessor.setBeanFactory(beanFactory);            this.lifecycleProcessor = defaultProcessor;            // 并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中            beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);            if (logger.isTraceEnabled()) {                logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +                        "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");            }        }    }

2.首先将刷新结束事件流传到生命周期处理器

private void startBeans(boolean autoStartupOnly) {        // 1.获取所有的Lifecycle bean        Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();        // 将Lifecycle bean 按阶段分组,阶段通过实现Phased接口失去        Map<Integer, LifecycleGroup> phases = new HashMap<>();        // 2.遍历所有Lifecycle bean,按阶段值分组        lifecycleBeans.forEach((beanName, bean) -> {            // autoStartupOnly=true代表是ApplicationContext刷新时容器主动启动;autoStartupOnly=false代表是通过显示的调用启动            // 3.当autoStartupOnly=false,也就是通过显示的调用启动,会触发全副的Lifecycle;            // 当autoStartupOnly=true,也就是ApplicationContext刷新时容器主动启动,只会触发isAutoStartup办法返回true的SmartLifecycle            if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {                // 3.1 获取bean的阶段值(如果没有实现Phased接口,则值为0)                int phase = getPhase(bean);                // 3.2 拿到寄存该阶段值的LifecycleGroup               LifecycleGroup group = phases.get(phase);                if (group == null) {                    // 3.3 如果该阶段值的LifecycleGroup为null,则新建一个                    group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);                    phases.put(phase, group);                }                // 3.4 将bean增加到该LifecycleGroup                group.add(beanName, bean);            }        });        // 4.如果phases不为空        if (!phases.isEmpty()) {            List<Integer> keys = new ArrayList<>(phases.keySet());            // 4.1 按阶段值进行排序            Collections.sort(keys);            // 4.2 按阶段值程序,调用LifecycleGroup中的所有Lifecycle的start办法            for (Integer key : keys) {                phases.get(key).start();            }        }    }

3.推送上下文刷新结束事件到相应的监听器

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {        Assert.notNull(event, "Event must not be null");        // Decorate event as an ApplicationEvent if necessary        // 1.如有必要,将事件装璜为ApplicationEvent        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 {            // 2.应用事件播送器播送事件到相应的监听器            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);        }        // Publish event via parent context as well...        // 3.同样的,通过parent公布事件.....        if (this.parent != null) {            if (this.parent instanceof AbstractApplicationContext) {                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);            }            else {                this.parent.publishEvent(event);            }        }    }

这外面调用的publishEvent办法,和咱们自定义的监听器调用的publishEvent是同一个办法,ContextRefreshedEvent是Spirng的一个事件称为上下文刷新结束事件,如果咱们在上下文刷新实现后要写一个公布事件,实现ApplicationListener<ContextRefreshedEvent>接口即可。

咱们在此举一个简略的例子。

这样,当 Spring 执行到 finishRefresh 办法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。

读者能够联合自定义事件比照一个和Spring提供的刷新上下文事件的区别,以便于更好的了解Spring的事件监听机制。

跟 ContextRefreshedEvent 类似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent。

好啦,Spirng的refresh办法到这里就完结啦,一共是九篇博客,实际上这也是Spirng的IOC的全部内容了,如果读者能把九篇的齐全消化,那么spring的IOC也就了解的七七八八了。