概述
本文深入分析 Spring IoC 容器体系,讲解 BeanFactory 过程分析以及 Bean 懒加载机制。
BeanFactory
子流程关键步骤
Resource 定位: 指定 Beandefinition 的资源定位过程,就是 JavaBean 信息的 XML 文件,将其封装为 Resource 对象。
BeanDefinition 载入: 把用户定义好的 JavaBean 表示为 IoC 容器内部的数据结构,这个容器内部的数据结构就是 BeanDefinition。
过程分析
子流程入口在 AbstractRefreshableApplicationContext#refreshBeanFactory 方法中。
loadBeanDefinitions(beanFactory): 加载应用中的 BeanDefinitions,依次调用多个类 loadBeanDefinitions 方法:
- 第一步:AbstractXmlApplicationContext
- 第二步:AbstractBeanDefinitionReader
- 第三步:XmlBeanDefinitionReader
- 第四步:XmlBeanDefinitionReader 的 doLoadBeanDefinition 方法
重点观察 XmlBeanDefinitionReader 类的 registerBeanDefinitions 方法,期间产生了多次重载调用。接着进入 createReaderContext 函数,随后会走到 DefaultNamespaceHandlerResolver,完成 NamespaceHandlerResolver 的初始化工作。
在 DefaultBeanDefinitionDocumentReader 中,找到 registerBeanDefinition 方法,根据 doRegisterBeanDefinitions,调用 parseBeanDefinition。解析 Bean 元素的过程在 processBeanDefinition 处,BeanDefinitionReaderUtils.registerBeanDefinition 完成了对 Bean 的注册。
Bean
Bean 的创建子流程入口在 AbstractApplicationContext#refresh() 方法的 finishBeanFactoryinitialization(beanFactory)处。
跟入后,可以看到最后的 preInstantiateSingletons,这里实例化所有立即加载的单例 Bean。最终跟入后,发现都是通过 getBean 方法来实例化的。
Lazy-init
延迟加载机制,普通 Bean 的初始化是在容器初始化阶段运行的,而被 lazy-init=true 的修饰的 bean,是从容器中第一次执行 context.getBean 的时候触发。
Spring 启动的时候会把所有 Bean 的信息(包括 XML 和注解)解析转化为 Spring 能够识别的 BeanDefinition 并存到 HashMap 里,给后续的初始化使用,然后对每个 BeanDefinition 进行处理,如果是懒加载则在容器初始化阶段不处理,其他的在容器初始化阶段进行初始化进行依赖注入。