spring-boot源码分析之BeanFactory · 贰

spring-boot源码分析之BeanFactory · 贰

前言

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

BeanFactory初始化

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

spring-boot源码分析之BeanFactory · 贰

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

createApplicationContext

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

spring-boot源码分析之BeanFactory · 贰

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

spring-boot源码分析之BeanFactory · 贰

AnnotationConfigServletWebServerApplicationContext实例化

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

spring-boot源码分析之BeanFactory · 贰

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

容器实例化

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

spring-boot源码分析之BeanFactory · 贰

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

spring-boot源码分析之BeanFactory · 贰

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

知识扩展

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

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

总结

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

– END –


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

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

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

(0)
小半的头像小半

相关推荐

发表回复

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