spring中循环依赖

注:单例的非构造方法依赖注入才能解决循环依赖

1.bean初始化的执行流程

(1)通过构造方法实例出一个对象(反射的方式,createBeanInstance)

  (2) 填充依赖的属性bean(populateBean)

  (3)执行初始化的方法(initialzeBean,会执行代理方法)

  (4)是否取实例化后的代理对象

2.详细流程

1.InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(Class beanClass,String beanName),在实例化前调用(可以创建代理对象,跳过后面的逻辑)

2.反射调用构造方法new一个bean对象(无参的构造器直接new个对象,有参的构造方法,参数按类型去beanFactory中依赖查找(如果匹配多个,则按字段名称去匹配))

3.MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class beanType,String beanName),可以修改the merged bean definition

4.InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(Object bean,String beanName),实例化后操作

5.InstantiationAwareBeanPostProcessor.postProcessProperties(PropertyValues pvs,Object bean,String beanName),填充属性(处理@Resource,@Autowired,@Value)

6.BeanPostProcessor.postProcessBeforeInitialization(Object bean,String beanName)在初始化方法前执行(注解@PostConstruct在此执行)

7.InitializingBean.afterPropertiesSet()

8.执行自定义初始化方法

9.BeanPostProcessor.postProcessAfterInitialization(Object bean,String beanName)在初始化方法执行后再执行(会执行创建代理逻辑)

3.循环依赖的三级缓存(都是map)

singletonObjects,earlySingletonObjects,singletonFactories

singletonObjects 中存放完全态的bean;

earlySingletonObjects 中存放只执行了步骤1的bean(这个bean可能是个代理对象,ObjectFactory.getObject()返回的)

singletonFactories中存放的是ObjectFactory

这三个map是互斥的,移动顺序是singletonFactories-->earlySingletonObjects-->singletonObjects

例如:A依赖B,B依赖A;

当从A开始初始化时,执行完步骤1,把ObjectFactory放入singleonFactories中,当执行步骤2时,发现依赖B;B则开始初始化,到B执行到步骤2时,发现依赖A,则去singleonFactories匹配到ObjectFactory,将ObjectFactory.getObject()的返回值(可能是创建的代理对象)放入earlySingletonObjects,B获取到了A,则继续执行步骤3,4,B执行完,再现次回到A的的步骤2,继续执行完它的步骤3(第4步时如果匹配成功,则取代理对象),最后将A实例放入singletonObjects,同时删除earlySingletonObjects和singletonFactories中的值,完成。

4.为什么要用三级缓存

解决循环依赖的对象是代理创建的逻辑

先行手动调用getEarlyBeanReference()就可以解决代理的问题,为什么还要用三级缓存?

循环依赖毕竟是少数情况,不能为了1%的情况让所有创建bean的逻辑都走一遍这个逻辑,影响效率

5.为了保持单例对象的一致性,所以代理类创建代理对象的这两个接口应该返回一致的值

public Object postProcessAfterInitialization(Object bean,String beanName)

public Object getEarlyBeanReference(Object bean,String beanName)

你可能感兴趣的:(spring,java,前端)