spring-boot源码分析之BeanFactory · 壹


前言

今天原本是打算分析beanFactory的,但由于昨天我们有一部分内容还没有分享完,所以今天就先开个倒车,把昨天的内容先讲清楚了再说别的,因此今天的内容主要就是对昨天分享内容的的补充。

当然,昨天我们分享的内容beanDefinitionNames也算是BeanFactory的核心属性,所以也不能说完全没有关系:

spring-boot源码分析之BeanFactory · 壹

而且从源码中我们可以看出来,beanDefinitionNamesbeanDefinitionMap这些属性的初始化大小,这也算是在学习beanFactory的相关知识吧。

BeanFactory

beanDefinitionNames内容补充

正式开始之前,我们先把昨天遗留的问题解决了。昨天,我们分享了一张beanDefinitionNames初始化的时序图,但是由于有一些内容没有梳理清楚,所以这里先做个补充。

spring-boot源码分析之BeanFactory · 壹
调用过程各方法作用

SpringApplication这里就不做过多说明了,我们在前面最开始的时候就已经分析过这个类的run方法,当时也已经介绍过这个类的这些方法,他们的主要作用就是为了初始化容器,在SpringApplication的最后一个refresh方法中,最后会调用AbstractApplicationContext自身的refresh方法,这里的AbstractApplicationContextApplicationContext的抽象实现,它实现了ConfigurableApplicationContext接口ConfigurableApplicationContext继承了ApplicationContext),我们的AnnotationConfigReactiveWebServerApplicationContext(默认容器)就是继承自它,不过并不是直接继承,它的父类继承了AbstractApplicationContext,关于容器这块的继承关系,我们改天抽个时间,专门分析下。

大部分继承了AbstractApplicationContext的容器都没有重写refresh方法,就算重写了这个方法,其内部也是调用了父类的refresh方法:

spring-boot源码分析之BeanFactory · 壹

我们看下refresh的实现源码:

 public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
   // Prepare this context for refreshing.
   prepareRefresh();

   // Tell the subclass to refresh the internal bean factory.
   ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

   // Prepare the bean factory for use in this context.
   prepareBeanFactory(beanFactory);

   try {
    // Allows post-processing of the bean factory in context subclasses.
    postProcessBeanFactory(beanFactory);

    // 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();

    // Initialize event multicaster for this context.
    initApplicationEventMulticaster();

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

    // Check for listener beans and register them.
    registerListeners();

    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);

    // 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();
   }
  }
 }

refresh方法内部,调用了很多其他方法,其中prepareRefresh的作用是为我们下面的刷新操作做准备,其内部主要是对配置的一些初始化操作:

spring-boot源码分析之BeanFactory · 壹

obtainFreshBeanFactory方法的作用是刷新beanFactory,主要是对beanFactory进行一些初始化操作,如果beanFactory已经存在,会将已有的beanFactory销毁,然后重新创建,最后将beanFactory返回:

spring-boot源码分析之BeanFactory · 壹

prepareBeanFactory方法的作用是对BeanFactory进行一些赋值和设置,为容器初始化操作做准备:

spring-boot源码分析之BeanFactory · 壹

postProcessBeanFactory方法就是我们昨天提到的会进行包扫描的那个方法,但由于basePackagesannotatedClasses都是空,所以其中的scan方法并不会被执行。这个方法实际的作用是,后置处理BeanFactory

spring-boot源码分析之BeanFactory · 壹

invokeBeanFactoryPostProcessors方法的作用是,实例化并调用所有注册的BeanFactory的后置处理器。我们昨天说的beanDefinitionNamesbeanDefinitionMap就是通过这个方法最终完成初始化的:

spring-boot源码分析之BeanFactory · 壹

registerBeanPostProcessors方法和它名字一样,它的作用就是注册bean的后置处理器:

spring-boot源码分析之BeanFactory · 壹

initMessageSource方法是进行消息源初始化的,主要是对web应用消息国际化提供支持的:

spring-boot源码分析之BeanFactory · 壹

initApplicationEventMulticaster,这个方法是初始化spring boot应用时间广播的,如果不指定的话,默认情况下为我们指定的是SimpleApplicationEventMulticaster

spring-boot源码分析之BeanFactory · 壹

onRefresh,这个方法是提供给子类初始化其他特殊bean对象的,默认实现为空,子类可根据需要重写:

spring-boot源码分析之BeanFactory · 壹

registerListeners方法是用来注册事件监听器的:

spring-boot源码分析之BeanFactory · 壹

finishBeanFactoryInitialization,完成beanFactory初始化,同时在方法内部会实例化剩余的单例类(不包括懒加载部分):

spring-boot源码分析之BeanFactory · 壹

finishRefresh,完成刷新,主要进行一些清理、刷新、事件推送等操作:

spring-boot源码分析之BeanFactory · 壹

总结

经过今天的补充之后,我相信各位小伙伴一定也对spring boot的启动和初始化过程有了更深刻的认识,因为我就是这样的感受。相比于昨天分享完内容的感受,今天我感觉整体来说要更好。一方面感觉spring boot启动和初始化的流程更清晰了,而且由于最近这几天一直在看spring boot的源码,看的多了感觉就没有那么难了,毕竟书读百遍其意自现,代码也是大同小异;另一方面在梳理分析的过程中,让我也能够清晰地看到下一步要分享的内容,明确后面的前进方向,这也算是意外的收获吧。

– END –


原文始发于微信公众号(云中志):spring-boot源码分析之BeanFactory · 壹

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/40524.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!