Spring-Bean的实例化过程
时序图
Bean的实例化过程
循环依赖解决
通过三级缓存解决。循环依赖只会出现在单例模式下,在prototype或其他模式下,循环依赖会直接报错。
循环依赖只会出现在单例实例无参构造函数实例化情况下
有参构造函数的加@Autowired 的方式循环依赖是直接报错的,多例的循环依赖也是直接报错的
步骤
- A类无参构造函数实例化后,设置三级缓存
- A类populateBean进行依赖注入,触发B类的getBean
- B类无参构造函数实例化后,设置三级缓存
- B类populateBean进行依赖注入,触发A类的getBean
- A类之前正在实例化,singletonsCurrentlyInCreation集合中已经有 A类,三级缓存中也有了,所以这时从三级缓存中拿到了提取暴露的A实例,该实例还没有进行B类属性的依赖注入,B类属性为空
- B类拿到A的提前暴露实例注入到A类属性中
- B类实例化已经完成,B的实例化由A类实例化中B属性的依赖注入触发的getBean操作进行的,现在B已经实例化了,所以A中B属性也就可以完成依赖注入了,这时A类的B属性已经有值了
- B类A属性指向的就是A类实例堆空间,所以B类A属性也有值了。
singletonObjects
一级缓存, 创建完成的Bean保存的位置
earlySingletonObjects
二级缓存,当前正在创建的Bean,已实例化正在填充属性的Bean。
singletonFactories
三级缓存,拿到的是ObjectFactory对象。
BeanPostProcessor接口
BeanPostProcessor接口类型实例是针对具体特定功能的埋点,在这个点会根据接口类型过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现,
获取有@Autowired注解的构造函数埋点
过滤的接口类型是SmartInstantiationAwareBeanPostProcessor
调用方法是determineCandidateConstructors
收集@Resource@Autowired@Value@PostConstruct@PreDestroy注解的方法和属性埋点
过滤的接口类型MergedBeanDefinitionPostProcessor
调用的方法PostProcessMergedBeanDefinition
循环依赖Bean的提取暴露埋点
SmartInstantiationAwareBeanPostProcessor
getEarlyBeanReference
阻止依赖注入埋点
InstantiationAwareBeanPostProcessor
postProcessAfterInstantiation
IOC/DI依赖注入埋点
InstantiationAwareBeanPostProcessor
postProcessProperties