BeanFactory

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_spring

子流程关键步骤

Resource 定位:指定 Beandefinition 的资源定位过程,就是 JavaBean 信息的 XML 文件,将其封装为 Resource 对象。

BeanDefinition 载入:把用户定义好的 JavaBean 表示为 IoC 容器内部的数据结构,这个容器内部的数据结构就是 BeanDefinition。

过程分析

子流程入口在 AbstractRefreshableApplicationContext#refreshBeanFactory 方法中:

AbstractRefreshableApplicationContext 类的内容如下:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springboot_02

方法中的 refreshBeanFactory 的内容如下:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springcloud_03

loadBeanDefinitions(beanFactory):加载应用中的 BeanDefinitions

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_开发语言_04


依次调用多个类 loadBeanDefinitions 方法:

  • 第一步:AbstractXmlApplicationContext
  • 第二步:AbstractBeanDefinitionReader
  • 第三步:XmlBeanDefinitionReader
  • 第四步:XmlBeanDefinitionReader 的 doLoadBeanDefinition 方法

一级一级走:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_开发语言_05

我们重点观察 XmlBeanDefinitionReader 类的 registerBeanDefinitions 方法,期间产生了多次重载调用。

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springcloud_06


我们接着进入 createReaderContext 函数:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_java_07


接着往后跟(后续的函数方法),最后会走到:DefaultNamespaceHandlerResolver,这里完成了 NamespaceHandlerResolver 的初始化工作。

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springcloud_08

我们在 DefaultBeanDefinitionDocumentReader 中,找到 registerBeanDefinition 方法:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_开发语言_09

我们根据 doRegisterBeanDefinitions:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_开发语言_10

当前方法的末尾,调用了 parseBeanDefinition:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springboot_11


继续跟入,此时的 parseDefaultElement 解析 Bean 元素:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_开发语言_12

这里就是解析 Bean 的过程:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_spring_13


我们继续向下找,processBeanDefinition,在这个地方,BeanDefinitionReaderUtils.registerBeanDefinition 完成了对 Bean 的注册:

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_spring_14

Bean

通过最开始的关键时机点分析,我们知道 Bean 的创建子流程入口在:

AbstarctApplicationContext#refresh()方法的 finishBeanFactoryinitialization(beanFactory)出:

(AbstractApplicationContext 中 refresh 函数中)

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_spring_15


跟入后,可以看到最后的:preInstantiateSingletons,这里实例化所有立即加载的单例 Bean

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springcloud_16


最终跟入后,我们发现都是通过 getBean 方法来实例化的。

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_java_17

lazy-init

延迟加载机制,普通 Bean 的初始化是在容器初始化阶段运行的,而被 lazy-init=true 的修饰的 bean,是从容器中第一次执行 context.getBean 的时候触发。
Spring 启动的时候会把所有 Bean 的信息(包括 XML 和注解)解析转化为 Spring 能够识别的 BeanDefinition 并存到 HashMap 里,给后续得初始化使用,然后对每个 BeanDefinition 进行处理,如果是懒加载则在容器初始化阶段不处理,其他的在容器初始化阶段进行初始化进行依赖注入。

Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init_springcloud_18