总分结构回答,突出关键接口、类、方法名
run -> AbstractApplicationContext.refresh()程序的入口
在IOC中的操作都是基于DefaultListableBeanFactory
bd对象保存在map集合中
refresh方法宝包括了整个Spring的执行流程和bean的完整生命周期
某些情况下实例化bean的过程比较复杂,可以实现BeanFactory接口定制bean的实例化逻辑
Spring是如何检测是否存在循环依赖的:
使用列表来记录正在创建中的bean,bean创建之前,先去记录中看一下是否在列表中,如果在说明存在循环依赖,如果不在,则将其加入到这个列表,bean创建完毕之后,将其再从列表中移除
问题1:谈谈对SpringIoc的理解
名词及注意:
循环依赖得以解决的根本愿意:Spring中bean的实例化和初始化是分开执行的
RuntimeBeanReference
三级缓存访问顺序:一级-》二级-》三级
objectFactories中保存的是lambda,当调用getObeject时,才会真正执行代码
优点:类似于回调机制,可以选择暴露
三级缓存放前提:
判断是否允许提前暴露 (单例bean、bean正在创建过程中、允许循环引用)
——————————————————————————————————————————
BeanFacoty:访问ioc容器的根接口
IOC Inversion of Controller(控制反转):关键点:谁控制谁?控制了什么? ioc不是一种技术,而是一种思想,在程序中主动控制对象的创建转为接受容器为调用者的成员进行赋值。
Spring提供了一个IOC容器对这种思想进行了落地实现,使用map结构来进行对象存储,ioc容器中通常存在三级缓存,使用singletonObjects保存成品对象,earlierSingletonObjects保存的是半成品对象,singletonFactories保存的是创建对象的工厂,bean对象的生命周期是IOC容器所管理的
BeanFactory,表示SpringIOC容器,实现类为DefaultListableBeanFactory【bean实例化和获取的具体类】
在IOC流程中,先是获取了一个BeanFactory的实现类DefaultListableBeanFactory(后续的操作都是基于此实例进行的),调用prepareFactory方法做了一些准备工作,各种(属性填充)bd对象在此载入(来源@ComponentScan @Import @Configuration xml ),生成相应的bd对象,。【在invokeBeanFactoryPostProcessors 前bd对象就存在,不过不是完整的bd对象,
bd对象的注册(也就是配置文件的读取是在实例化ApplicaitonContext过程中就完成的)
xml的注册 xml - 》dom4j -> document ->nodeList
注解:获取要扫描的类,判断类上是否存在注解
BeanFactoryPostProcessors是Spring的一个拓展点,(二次开发使用较多)】对BeanFactory提供了额外的拓展操作,如:字符串的替换
finishBeanFactoryInitialization中完成bean对象的创建和初始化工作
方法调用过程:getBean -》doGetBean -》createBean -> doCreateBean -populateBean
流程:获取所有的beanName(注意不是从bd对象中获取)
以A中依赖bean,B中依赖A为例,总共需要执行两次该过程 1.从三级缓存中查找是否存在bean,不存在根据beanName获取bd对象,根据bd对象判断是否是单例bena,分支-》单列bean和原型bean创建
创建bean:
createBeanInstance:创建bean实例
允许提前暴露,则将创建bean的factory添加到三级缓存中
populateBean bean属性的填充
population中进行:获取要注入属性的RuntimeBeanReference,进行解析,getBean
先实例化A
此时三级缓存中已经有对象A和对象B
第三遍getBean(当查看三级缓存中存在对象A时【将A对象存入二级缓存中,并删除三级缓存中对的A对象】,返回实例化对象)