本文主要讨论spring容器初始化时:
1. BeanFactory及BeanDefinition的创建及加载注册流程
2.Bean创建流程
3.Bean创建流程之延迟加载
4.Spring通过三级缓存处理对象循环依赖问题
1. spring容器初始化之BeanFactory及BeanDefinition的创建及加载注册流程
通过new ClassPathXmlApplicationContext("classpath:springContext.xml")开启Spring容器,实际调用了AbstractApplicationContext的refresh()方法, 在refresh()方法中,包含了Spring容器启动的各个步骤,其中 obtainRefreshBeanFactory中完成了 BeanFactory的初始化, XML解析,<bean>标签及相关属性封装到BeanDefinitionHolder(此对象调用getBeanDefinition可获取BeanDefinition对象,并存放在Hashmap集合中)中 这一系列操作;
2. Bean的创建流程
在refresh()方法中,finishBeanFactoryInitialization方法中,则完成了Bean的创建,包含:实例化所有立即加载的单例bean,填充属性,并根据各个bean是否实现相应的Aware接口、定义了对应的初始化方法、是否设置了BeanPostProcessor后置处理器等,从而依次执行对应的方法
整合整合SpringBean生命周期分析图如下
3.Bean创建流程之延迟加载
设置对象的lazy-init="true" 延迟加载后,在 Spring容器初始化Bean创建流程中, 在DefaultListableBeanFactory的preInstantiateSingletons()方法中,在调用AbstractBeanFactory的getBean方法前,会判断 !bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit() 此条件将不满足,不会调用getBean方法;而在程序调用applicationContext.getBean("aBean")方法时,将会直接进入AbstractBeanFactory的doCreateBean(),开始Bean的创建流程;
4.spring对Bean对象间循环依赖问题的代码处理
Bean对象的循环依赖是指 ClassA 引用了ClassB作为属性,同时ClassB也引用了ClassA作为属性;
针对此问题,Spring设置了三级缓存机制处理此问题:
4.1 在A通过构造器初始化后,将A对象直接暴露到Spring容器中(三级缓存);
4.2 A在对属性封装值时,Spring会先从容器中获取B,此时B不存在,调用getBean方法创建ClassB;
4.3 容器创建B执行构造器初始化后,也会将B直接暴露在Spring容器中(三级缓存);
4.4 容器在对B进行属性封装时,需要将A设置进B中,Spring优先从容器中获取A,此时能直接拿到A的实例,并将三级缓存中的A 放入二级缓存中。B完成创建;
4.5 B完成创建后,继续A的赋值属性操作,完成A的创建;
自此AB两个对象都完成了对象初始化操作
可以处理循环依赖的前提:
单例bean通过set方法或者@Autowired注入的循环依赖