一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
相信大家在面试过程中,都会被问到过这样的问题,bean的生命周期是什么?在我被问到的时候,基本上就是将这个过程背诵一遍,如下图,没仔细关注过源码的实现过程,今天我就依照这这个流程去跟踪遍源码,让自己能够理解这个过程。
bean对象解析过程
使用spring已经多年,却从来没有仔细研究过spring bean的初始化过程以及原理。知其然而不知其所以然,当面遇到比较深度的问题的时候,就无法解决或者需要花费大量问题方可解决。本文主要探索bean的初始化过程,
解析XML的核心类
- XmlBeanDefinitionReader:Xml资源的阅读器,将xml解析成Document, 判断当前是否正在加载此资源文件。
从ThreadLocal对象resourcesCurrentlyBeingLoaded中检查次Resource是否正在加载中,如果正在加载抛出异常,否则加载Resource文件。避免因为循环引用导致问题。
//通过Resource创建InputSource
InputStream inputStream = encodedResource.getResource().getInputStream();
InputSource inputSource = new InputSource(inputStream);
// 加载文档生成Document对象
Document doc = doLoadDocument(inputSource, resource);
//创建BeanDefinitionDocumentReader,调用registerBeanDefinitions进行解析并注册到BeanFactory中
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
documentReader.registerBeanDefinitions(doc,createReaderContext(resource));
2.DefaultBeanDefinitionDocumentReader:Document阅读器,将document解析成Element、Node、Attribute,以便于后续解析。
1.创建BeanDelinitionParserDelegate
2.调用parseBeanDefinitions(root,this.delegate)方法进行解析, 根据element的不同,分别解析
this.delegate= createDelegate(getReaderContext(), root, parent);
preProcessXml(root);
parseBeanDefinitions(root,this.delegate);
postProcessXml(root);
3.BeanDefinitionParserDelegate:解析xml生成BeanDefinition的委派类。所有解析过程由此类完成
检查bean id是否重复,如果重复则抛出异常。 解析Bean,
BeanDefinitionDocumentReader会生成BeanDelinitionParserDelegate。当xml中import进来多个xml文件时,因为spring会为每一个xml文件生成BeanDefinitionDocumentReader对象,所以当一个id同时存在两个xml文件中的时候,是不会出现id重复的异常的。
4.DefaultListableBeanFactory
xml解析完以后,都注册到BeanFactory。后续通过BeanFactory可以源源不断的创建实例。
Bean的创建
当我们调用getBean方法获取Bean的时候,首先是通过getSingeleton方法从缓存中获取Instance。
如果获取到Instance,检查是否为FactoryBean,如果不是直接返回;如果是,获取FactoryBean的Object对象。其中有一步是检查缓存中是否存在Object,如果不存在,那么新建一个,缓存起来,见流程图。
如果获取不到Instance,检查是singletion还是prototype,如果是singletion,那么检查之前是否已经实例化过,如果已经实例化直接返回,如果没有实例化,则重新实例化。Prototype和singletion未实例化的场景基本一致。
好了,本文就给大家介绍到这里,感觉有帮助的,留下个赞或评论再走吧!谢啦~ 💐