zoukankan      html  css  js  c++  java
  • Spring 源码学习 09:refresh 大概流程

    前言

    前面的准备工作结束之后,就是进入核心代码 refresh。

    源码

    public void refresh() throws BeansException, IllegalStateException {
        // 加锁
        synchronized (this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
            // 准备一些上下文
            prepareRefresh();
    
            // 获取准备后的 beanFactory  DefaultListableBeanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // 准备 BeanFactory
            prepareBeanFactory(beanFactory);
    
            try {
                // 允许在上下文子类中对bean工厂进行后处理。
                postProcessBeanFactory(beanFactory);
    
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    
                // 在上下文中调用注册为 beanFactory 后置处理器
                // 就是实现了 BeanFactoryPostProcessor 的 bean
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // 注册后置处理的Bean到容器当中
                // 就是扩展了 BeanPostProcessor 的 Bean
                registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
    
                // 为此上下文初始化消息源。
                // 初始化国际化工具 MessageSource
                initMessageSource();
    
                // 为此上下文初始化事件广播器。
                initApplicationEventMulticaster();
    
                // 在特定上下文子类中初始化其他特殊bean。子类可以自己实现
                onRefresh();
    
                // 检查并注册监听器。
                registerListeners();
    
                // 实例化所有剩余的(非延迟初始化)单例。
                finishBeanFactoryInitialization(beanFactory);
    
                // 最后一步: 完成此上下文的刷新,调用 LifecycleProcessor 的 onRefresh()方法并发布
                finishRefresh();
            }
    
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
    
                // 销毁已创建的单例以避免资源悬挂。
                destroyBeans();
    
                // 重置活动状态
                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();
                contextRefresh.end();
            }
        }
    }
    

    源码就是密密麻麻的一大堆,源码上有相应的注释。

    下面就根据流程,一步一步的深入源码,了解到每一步都是做什么了。

    容器刷新准备

    prepareRefresh 这一步主要是准备一些上下文信息。就不过多介绍了。

    obtainFreshBeanFactory

    下面关注初始化 BeanFactory 这一步:

    进入源码:

    通过 Debug 可以看出 refreshBeanFactory() 这一步调用的是 org.springframework.context.support.GenericApplicationContext#refreshBeanFactory 中实现的方法。

    继续跟进

    发现这块判断了一个 refreshed 刷新状态。

    refreshBeanFactory 方法也有另一个实现是在 AbstractRefreshableApplicationContext 中, 只不过我的断点没有断进去,这块也一起看下。

    protected final void refreshBeanFactory() throws BeansException {
        // 如果存在 BeanFactory 则销毁 Bean 并关闭 BeanFactory
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建一个默认的 BeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // 设置属性
            customizeBeanFactory(beanFactory);
            // 加载 Bean 信息
            loadBeanDefinitions(beanFactory);
    
            this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    

    其中会创建 BeanFactory 并加载 BeanDefinition。只不过我暂时没有断到,所以等后面遇到之后再详细介绍。

    总结

    本文简单介绍了 refresh 的流程,并介绍了前两个部分:

    1. prepareRefresh 准备上下文信息
    2. obtainFreshBeanFactory 初始化 BeanFactory

    相关推荐

  • 相关阅读:
    java中获取类资源的不同姿势
    Jdk动态代理与Cglib动态代理
    Spring AOP
    Spring Ioc、DI
    windows 8.1 专业版 visual stuido 2015 安装失败
    win7 共享需要密码问题
    protobuffer .net 序列化
    【转载】SQL Server 2005数据库用户权限管理的设置
    【转载】mongoDB基本使用手册
    【转载】Thread.sleep(0)的意义
  • 原文地址:https://www.cnblogs.com/liuzhihang/p/source-spring-9.html
Copyright © 2011-2022 走看看