spring每次在创建对象之前都是先从容器里查找该bean对象是否存在,getBean(beanName),不存在才会创建doGetBean。
假设A、B两个对象相互依赖:
spring初始化流程:从DefaultListableBeanFactory 方法 getBean(beanName) 进入——>doGetBean——>getSingleton(beanName)
——>getSingleton(beanName,lambda),lambda内部调用createBean——> doCreateBean——>createBeanInstance——>addSingletonFactory(添加bean早期对象到三级缓存)——>populateBean——>initializeBean
注意getSingleton(beanName)与getSingleton(String beanName, ObjectFactory<?> singletonFactory)是DefaultSingletonBeanRegistry的重载方法,后者内部会执行createBean方法。
①、A实例化
在第一次实例化前getBean会调用getSingleton判断缓存中是否存在A,不存在且A是单例Bean,调用getSingleton(beanName,lambda),lambda中会执行createBean方法开始创建A,通过doCreateBean调用createBeanInstance完成A的实例化。(此时是未完成初始化的A)
同时通过addSingletonFactory方法将A的早期对象添加到三级缓存中,此时的key是对象名,value是一个lambda表达式addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));。
②、A属性填充
完成实例化后,对A进行属性填充,调用populateBean方法populateBean(beanName, mbd, instanceWrapper);此时将对A中的属性B进行设置
populateBean调用applyPropertyValues方法根据属性名称设置值时,会调用resolveValueIfNecessary方法判断value是不是RuntimeBeanReference(引用类型),如果是,此时会调用resolveReference()方法进行B引用的解析和自动装配。在resolveReference()方法中通过 bean = this.beanFactory.getBean(refName);进行B对象的初始化流程,这里的beanFactory是AbstractBeanFactory的对象。
③、实例化、初始化B
和A实例化一样,此时缓存也没有B对象,执行相同的流程。当B的早期对象添加进三级缓存后,调用populateBean进行属性设置,此时B依赖A,所以会对A进行设置。同一样会经过resolveValueIfNecessary判断是否为引用类型,再次进入获取对象A的流程getSingleton(beanName),此时可以在三级缓存中根据A的名称获取name所对应的早期对象,通过方法getEarlyBeanReference获取A对象,再把拿到的A对象put到二级缓存earlySingletonObjects中,同时删除三级缓存。A属性设置完成后,调用initializeBean方法完成B的初始化操作。此时lambda表达式中create方法的流程执行完毕,B初始化完成,继续执行getSingleton(String beanName, ObjectFactory<?> singletonFactory)后面的逻辑,调用addSingleton(beanName, singletonObject);方法,将B添加到一级缓存并清除B的二级、三级缓存。
④、初始化A
完成B初始化后,resolveValueIfNecessary方法已经得到了一个完整的B对象,会接着上面2后面的流程给A设置B属性。然后调用initializeBean方法完成A的初始化操作。和3一样,调用addSingleton(beanName, singletonObject);方法,将A添加到一级缓存并清除A的二级、三级缓存。
方法说明:
1)、addSingletonFactory,是完成实例化bean后紧接着调用的,作用是向三级缓存中添加尚未初始化的bean(只是分配了内存地址);
2)、getSingleton(String beanName, ObjectFactory<?> singletonFactory),判断缓存中是否存在该bean,标记正在创建的bean(调用isSingletonCurrentlyInCreation方法向singletonsCurrentlyInCreation列表添加正在创建的bean),singletonFactory创建bean的工厂,可传入lambda表达式;
3)、getSingleton(String beanName),判断缓存中是否存在该bean,且bean是否正在创建(通过isSingletonCurrentlyInCreation方法判断singletonsCurrentlyInCreation集合里是否包含bean名称)。