Java-36 深入浅出 Spring - IoC容器体系 BeanFactory过程分析 Bean Lazy-Init
点一下关注吧!!!非常感谢!!持续更新!!!
大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html
目前已经更新到了:
- MyBatis(已更完)
- Spring(正在更新…)
BeanFactory
子流程关键步骤
Resource 定位:指定 Beandefinition 的资源定位过程,就是 JavaBean 信息的 XML 文件,将其封装为 Resource 对象。
BeanDefinition 载入:把用户定义好的 JavaBean 表示为 IoC 容器内部的数据结构,这个容器内部的数据结构就是 BeanDefinition。
过程分析
子流程入口在 AbstractRefreshableApplicationContext#refreshBeanFactory 方法中:
AbstractRefreshableApplicationContext 类的内容如下:
方法中的 refreshBeanFactory 的内容如下:
loadBeanDefinitions(beanFactory):加载应用中的 BeanDefinitions
依次调用多个类 loadBeanDefinitions 方法:
- 第一步:AbstractXmlApplicationContext
- 第二步:AbstractBeanDefinitionReader
- 第三步:XmlBeanDefinitionReader
- 第四步:XmlBeanDefinitionReader 的 doLoadBeanDefinition 方法
一级一级走:
我们重点观察 XmlBeanDefinitionReader 类的 registerBeanDefinitions 方法,期间产生了多次重载调用。
我们接着进入 createReaderContext 函数:
接着往后跟(后续的函数方法),最后会走到:DefaultNamespaceHandlerResolver,这里完成了 NamespaceHandlerResolver 的初始化工作。
我们在 DefaultBeanDefinitionDocumentReader 中,找到 registerBeanDefinition 方法:
我们根据 doRegisterBeanDefinitions:
当前方法的末尾,调用了 parseBeanDefinition:
继续跟入,此时的 parseDefaultElement 解析 Bean 元素:
这里就是解析 Bean 的过程:
我们继续向下找,processBeanDefinition,在这个地方,BeanDefinitionReaderUtils.registerBeanDefinition 完成了对 Bean 的注册:
Bean
通过最开始的关键时机点分析,我们知道 Bean 的创建子流程入口在:
AbstarctApplicationContext#refresh()方法的 finishBeanFactoryinitialization(beanFactory)出:
(AbstractApplicationContext 中 refresh 函数中)
跟入后,可以看到最后的:preInstantiateSingletons,这里实例化所有立即加载的单例 Bean
最终跟入后,我们发现都是通过 getBean 方法来实例化的。
lazy-init
延迟加载机制,普通 Bean 的初始化是在容器初始化阶段运行的,而被 lazy-init=true 的修饰的 bean,是从容器中第一次执行 context.getBean 的时候触发。
Spring 启动的时候会把所有 Bean 的信息(包括 XML 和注解)解析转化为 Spring 能够识别的 BeanDefinition 并存到 HashMap 里,给后续得初始化使用,然后对每个 BeanDefinition 进行处理,如果是懒加载则在容器初始化阶段不处理,其他的在容器初始化阶段进行初始化进行依赖注入。