Spring bean初始化原理

208 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

相信大家在面试过程中,都会被问到过这样的问题,bean的生命周期是什么?在我被问到的时候,基本上就是将这个过程背诵一遍,如下图,没仔细关注过源码的实现过程,今天我就依照这这个流程去跟踪遍源码,让自己能够理解这个过程。

image.png

bean对象解析过程

使用spring已经多年,却从来没有仔细研究过spring bean的初始化过程以及原理。知其然而不知其所以然,当面遇到比较深度的问题的时候,就无法解决或者需要花费大量问题方可解决。本文主要探索bean的初始化过程,

解析XML的核心类

  1. 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未实例化的场景基本一致。

好了,本文就给大家介绍到这里,感觉有帮助的,留下个赞或评论再走吧!谢啦~ 💐