Spring 源码学习 09:refresh 大概流程
发布日期:2021-05-19 03:30:44 浏览次数:6 分类:博客文章

本文共 3425 字,大约阅读时间需要 11 分钟。

前言

前面的准备工作结束之后,就是进入核心代码 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

相关推荐

转载地址:https://www.cnblogs.com/liuzhihang/p/source-spring-9.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Spring 源码学习 03:创建 IoC 容器的几种方式
下一篇:Spring 源码学习 08:register 注册配置类

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月31日 16时03分58秒