Spring源码之九finishRefresh详解

Posted 程序员田同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码之九finishRefresh详解相关的知识,希望对你有一定的参考价值。

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 Springs 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也就理解的七七八八了。

以上是关于Spring源码之九finishRefresh详解的主要内容,如果未能解决你的问题,请参考以下文章

基础总结篇之九:Intent应用详解

机器学习中的概率模型和概率密度估计方法及VAE生成式模型详解之九(第5章 总结)

Spring Boot源码中模块详解

Spring源码之Spring后置处理器详解

Spring源码之Spring后置处理器详解

Mysql数据库理论基础之九---四类隔离级别