Spring源码分析

本文主要讨论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注入的循环依赖

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值