• spring-boot源码分析之BeanFactory · 贰


    前言

    BeanFactoryspring boot的最重要的核心组件,当然也是spring boot非常基础的组件,所以梳理清楚BeanFactory的源码才是梳理清楚Spring boot源码的关键。前天,我们分享了beanDefinitionNamesbeanDefinitionMap的初始化过程,虽然过程中有涉及到beanFactory的相关知识点,但是关于beanFactroy我们还没有正式地分析过它,关于它的初始化过程,也是一无所知,为了更系统地了解beanFactory,从今天开始我们开始更系统地分析beanFactory的相关源码,下面我们就先来看下BeanFactory的初始化过程。

    BeanFactory初始化

    今天我们依然是从一张时序图开始讲起,下面这张时序图就是spring boot容器的BeanFactory初始化过程,beanFactory初始化其实是和容器的初始化同时完成的,它也是容器初始化过程中的重要一步:

    在上面的时序图中,最关键的内容就是AnnotationConfigServletWebServerApplicationContext的实例化过程,这里面涉及到java类的初始化流程:创建子类时,必须先调用父类无参构造方法,所以AnnotationConfigServletWebServerApplicationContext是在所有父类实例化完成后,才完成它自己的实例化过程的。下面我们就来看AnnotationConfigServletWebServerApplicationContext的初始化流程。

    createApplicationContext

    debug的过程中,我发现 BeanFactory在容器被创建后就已经被初始化,这也就是说BeanFactory其实是在spring boot容器创建过程中被初始化的,所以我们今天主要就是研究容器创建过程,也就是createApplicationContext()方法:

    关于createApplicationContext这个方法,我们前面已经展示过了,它的作用就是通过反射创建容器实例:

    AnnotationConfigServletWebServerApplicationContext实例化

    通过跟踪代码,最终可以确认,调用的是AnnotationConfigServletWebServerApplicationContext无参构造方法:

    所以下面就是对AnnotationConfigServletWebServerApplicationContext的实例化,由于容器这块继承关系比较复杂,所以实例化顺序也比较复杂。

    容器实例化

    虽然各位小伙伴可能很清楚java对象实例化过程,但是我觉得还是有必要再补充说明下。在有继承关系的java对象实例化过程中,如果当前类继承了父类,在实例化当前类时,先要调用父类的无参构造方法(就算不指定,也会隐式调用)。所以,在这里初始AnnotationConfigServletWebServerApplicationContext时,会先调用它的父类无参构造方法,下面是AnnotationConfigServletWebServerApplicationContext的继承关系,看起来确实很复杂:

    在跟踪代码的过程中,最终我确认BeanFactory是在GenericApplicationContext的无参构造方法中完成初始化的,也就是AnnotationConfigServletWebServerApplicationContext父类的父类的父类:

    所以初始化的过程就是,AnnotationConfigServletWebServerApplicationContext的无参构造方法中先调用ServletWebServerApplicationContext的无参构造方法,ServletWebServerApplicationContext的无参构造方法中先调用GenericWebApplicationContext的无参构造方法,GenericWebApplicationContext的无参构造方法先调用GenericApplicationContext的无参构造方法(无限套娃)……

    知识扩展

    后续的调用这里就直接省略了,因为他们和BeanFactory没有关系,而且因为继承关系过于复杂,所以这里我们要尽可能简单。在这里所有的初始化操作中,调用父类构造方法始终是首先被执行的,也必须首先被执行(首先调用父类的无参构造方法),这也就是为什么我们在写类的有参构造方法的时候,如果父类没有无参构造方法时,必须显式调用父类有参构造方法,且必须放在第一行的原因:

    总结

    截止到今天,我们已经梳理清楚beanFactory的两块内容,一个是beanDefinitionNamesbeanDefinitionMap,他们都是beanFactory的核心属性,另一块就是我们今天的BeanFactory的初始化,下一步应该还是会进一步深挖beanFactory的相关知识点,因为从一开始我的想法就是要找到spring boot包扫描和实例化bean的相关逻辑,但到目前为止还没有理清楚这一块的逻辑和流程,不过我相信很快我们就能完成这个目标了,因为我们的每一步都在更靠近目标……

  • 相关阅读:
    东边日出西边雨
    ZooKeeper学习(一)了解ZooKeeper
    linux学习(七)文件打包和压缩命令
    linux学习(六)Linux yum 命令
    linux学习(五)Linux 文件与目录管理
    linux学习(四)Linux 文件基本属性
    linux学习(三)Linux 系统目录结构
    linux学习(二)认识Linux
    linux学习(一)认识阿里云
    多线程实战【面试题形式】
  • 原文地址:https://www.cnblogs.com/caoleiCoding/p/15232229.html
Copyright © 2020-2023  润新知