spring-boot源码分析之beanFactory · 肆

前言

昨天我们又分析了容器的创建过程,从容器的创建过程中,我们找到了beanFactory实例化后最基本的初始化——注册需要忽略的接口(ignoreDependencyInterface)、注册配置处理器(registerAnnotationConfigProcessors),beanFactory剩余的初始化操作都在后面的方法中,今天我们先来看prepareContext,虽然在prepareContext前面还有一个getSpringFactoriesInstances方法,但是这个方法并没有和beanFactory进行交互,所以就直接跳过了。

spring-boot源码分析之beanFactory · 肆

prepareContext

关于这个方法,我们前面已经分析过了,但基本上都是一带而过,所以今天我们就沿着beanFactory的初始化过程再来看下这个核心方法:

spring-boot源码分析之beanFactory · 肆

我们先来梳理下这个方法的执行流程:

  • 设置容器环境(context.setEnvironment),这一步操作基本与beanFacotry没有关系,有的也是一些取值操作,并没有往beanFactory中注册数据:

    spring-boot源码分析之beanFactory · 肆

  • 容器后置处理(postProcessApplicationContext),这个方法内部主要有三步操作。第一步是往beanFactory中注册beanName生成器,但由于默认情况下这个配置为空,所以并未进行注册操作;第二步是设置容器的资源加载器,由于resourceLoader是空,所以这里也没有设置;最后一步是注册转换服务,默认情况下会为我们注册136个转换器,这些转换器的作用就是进行类型转换,如果能在实际开发中用起来,那也是美滋滋了:

    spring-boot源码分析之beanFactory · 肆

    可以看到默认情况下为我们注册的转换器包括了StringDate这种常用的转换,当然我们也可以定义自己的转换器,这个我记下来,后面专门出一期demo示例。

    spring-boot源码分析之beanFactory · 肆

  • 初始化操作(applyInitializers),这个方法我们昨天已经分析过了,这里就不再赘述了,后面关于ApplicationContextInitializer的初始化我也会专门做一期demo分享的。

  • 绑定容器初始化事件(contextPrepared),这个方法在容器创建并准备好之后,资源加载完成前执行,这一步和beanFactory也没有关系

    spring-boot源码分析之beanFactory · 肆

  • 打印startupInfo。下面那一段代码就是打印启动日志信息, 默认情况下logStartupInfotrue,所以控制台会输出两行日志:

    spring-boot源码分析之beanFactory · 肆

  • 获取beanFactorycontext.getBeanFactory()),这个是为了方便后面注册数据,因为紧接着就需要把springApplicationArgumentsspringBootBanner等注册到beanFactory中:

    spring-boot源码分析之beanFactory · 肆

    最终registerSingleton方法会把他们注册到singletonObjects容器中,从名字我们就可以看出来,这是个存放单例对象的容器。

    spring-boot源码分析之beanFactory · 肆

  • 设置是否允许同名覆盖(setAllowBeanDefinitionOverriding),默认情况下为trueallowBeanDefinitionOverriding属性默认值)。如果为true,后面的BeanDefinition数据会将前面的覆盖掉。但是默认启动时,spring boot会将它该为false

    spring-boot源码分析之beanFactory · 肆

  • 添加beanFactory懒加载后置处理器(addBeanFactoryPostProcessor),由于默认情况下并未启动懒加载,所以默认情况下懒加载后置处理器也不会被添加

    spring-boot源码分析之beanFactory · 肆

  • 获取所有资源(getAllSources),默认情况下只包括当前spring boot项目的主类,同时关联了包括classLoaderpackages等数据

    spring-boot源码分析之beanFactory · 肆

  • 将资源加载到容器中(load,官方文档给的解释是bean)。这个方虽然看起来其貌不扬,但是内部操作还是蛮多的。本来内容已经写出来了,但是介于篇幅我决定把剩余内容放到明天分享,当然也是因为load方法确实也比较重要,其内部不仅包括了scanner的初始化,而且包括了filter的相关内容,这些都算是spring boot的核心内容,所以还是要尽可能详细些。

总结

原本是打算把prepareContext的内容一次性分享完的,但是实际分享的时候,发现内容还是蛮多的,特别是load方法,一个看起来小小的方法,没想到它的内部初始化操作还挺复杂的。不过,经过今天的梳理之后,我感觉对prepareContext认识要比之前清晰多了,而且在分析的过程中,还发现了两个需要demo实践的内容,相关内容的flag已经立起来了,后面就该填坑了,这也算是意外的收获吧。

好了,今天就先到这里吧!

上一篇:JAVA 面试遇到的常见问题


下一篇:spring成神之路第五十五篇:spring 上下文生命周期