一. spring启动过程中循环依赖相关的流程
二. 过程分析
我们假设有两个Bean, beanName分别是A和B,其中A被切面C切中。
源码入口
//参考<> 3. Bean实例化入口
//入口refresh--> finishBeanFactoryInitialization-->
//DefaultListableBeanFactory preInstantiateSingletons()
for (String beanName : beanNames) {
//循环遍历所有beanNames,我们假设A先遍历到
//非抽象&单例的&非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
... ... ... ...
getBean(beanName);
... ... ... ...
}
}
---
@Override
public Object getBean(String name) throws BeansException {
//真正的获取bean的逻辑
return doGetBean(name, null, null, false);
}
2.1 从缓存中获取A
singletonObjects为一级缓存,里边存放已完整创建的单例Bean。 这里获取A时,一级缓存不存在,且isSingletonCurrentlyInCreation为false,此时正在创建Bean集合中没有bean A。所有没有获取到缓存。
//doGetBean方法
Object sharedInstance = getSingleton(beanName);
//实现allowEarlyReference=true
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
/**
* 第一步:我们尝试去一级缓存(单例缓存池中去获取对象,一般情况从该map中获取的对象是直接可以使用的)
* IOC容器初始化加载单实例bean的时候第一次进来的时候 该map中一般返回空
*/
Object singletonObject = this.singletonObjects.get(beanName);
/**
* 若在第一级缓存中没有获取到对象,并且singletonsCurrentlyInCreation这个list包含该beanName
* IOC容器初始化加载单实例bean的时候第一次进来的时候 该list中一般返回空,但是循环依赖的时候可以满足该条件
*/
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
/**
* 尝试去二级缓存中获取对象(二级缓存中的对象是一个早期对象)
* 何为早期对象:就是bean刚刚调用了构造方法,还来不及给bean的属性进行赋值的对象(纯净态)
* 就是早期对象
*/
singletonObject = this.earlySingletonObjects.get(beanName);
/**
* 二级缓存中也没有获取到对象,allowEarlyReference为true(参数是有上一个方法传递进来的true)
*/
if (singletonObject == null && allowEarlyReference) {
/**
* 直接从三级缓存中获取 ObjectFactory对象 这个对接就是用来解决循环依赖的关键所在
* 在ioc后期的过程中,当bean调用了构造方法的时候,把早期对象包裹成一个ObjectFactory
* 暴露到三级缓存中
*/
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
//从三级缓存中获取到对象不为空
if (singletonFactory != null) {
/**
* 在这里通过暴露的ObjectFactory 包装对象中,通过调用他的getObject()来获取我们的早期对象
* 在这个环节中会调用到 getEarlyBeanReference()来进行后置处理
*/
singletonObject = singletonFactory.getObject();
//把早期对象放置在二级缓存,
this.earlySingletonObjects.put(beanName, singletonObject);
//ObjectFactory 包装对象从三级缓存中删除掉
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
2.2 设置正在创建
缓存中没有,开始创建,先通过beforeSingletonCreation方法,将beanA放入正在创建Bean的集合中
////doGetBean方法
//创建单例bean
if (mbd.isSingleton()) {
//把beanName 和一个singletonFactory 并且传入一个回调对象用于回调
sharedInstance = getSingleton(beanName, () -> {
try {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//DefaultSingletonBeanRegistry.getSingleton
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
... ... ... ...
beforeSingletonCreation(beanName);
... ... ... ...
singletonObject = singletonFactory.getObject();
newSingleton = true;
... ... ... ...
if (newSingleton) {
// <5> 加入缓存中
addSingleton(beanName, singletonObject);
}
... ... ... ...
}
protected void beforeSingletonCreation(String beanName) {
//若singletonsCurrentlyInCreation 没添加成功
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
/**
* 把对象加入到单例缓存池中(所谓的一级缓存 并且考虑循环依赖和正常情况下,移除二三级缓存)
* @param beanName bean的名称
* @param singletonObject 创建出来的单实例bean
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//加入到单例缓存池中
this.singletonObjects.put(beanName, singletonObject);
//从三级缓存中移除(针对的不是处理循环依赖的)
this.singletonFactories.remove(beanName);
//从二级缓存中移除(循环依赖的时候 早期对象存在于二级缓存)
this.earlySingletonObjects.remove(beanName);
//用来记录保存已经处理的bean
this.registeredSingletons.add(beanName);
}
}
在创建BeanA之前,先检查mbd.getDependsOn();是否为空,这里的dependOn非循环依赖的依赖,而是 @DependsOn(value = {"dependsA"}) 手动添加的依赖。
2.3 实例化A
上一步源码中getSingleton是传入一个回调函数,然后再singletonFactory.getObject()时执行。即执行createBean(beanName, mbd, args);
//AbstractAutowireCapableBeanFactory.createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 解析类
... ... ... ...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
... ... ... ...
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
... ... ... ...
//实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
final Object bean = instanceWrapper.getWrappedInstance();
... ... ... ...
}
2.4 放入三级缓存
上一步完成实例化后。接着判断是否需要暴露早期的Bean实例,此时条件满足
earlySingletonExposure=true, 执行addSingletonFactory方法,但是这里没有直接将早期的Bean放入缓存,放入的是一个回调。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//把我们的早期对象包装成一个singletonFactory对象 该对象提供了一个getObject方法,该方法内部调用getEarlyBeanReference方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected void addSingletonFactory(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//同步加锁
synchronized (this.singletonObjects) {
//单例缓存池中没有包含当前的bean
if (!this.singletonObjects.containsKey(beanName)) {
//加入到三级缓存中,,,,,暴露早期对象用于解决循环依赖
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
2.4 属性注入B
执行完三级缓存set逻辑,接着开始准备属性注入. 由于我们假设A依赖B,所有这里会执行BeanB的获取。即回到和A相同的开始——getBean
populateBean(beanName, mbd, instanceWrapper);
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
... ... ... ...
//获取bean定义的属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
... ... ... ...
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//按照name注入
autowireByName(beanName, mbd, bw, newPvs);
//按照type注入
autowireByType(beanName, mbd, bw, newPvs
... ... ... ...
}
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
... ... ... ...
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
}
... ... ... ...
}
2.5 BeanB属性注入A
遵循前边相同的流程,getBean 获取B,最终执行B的属性注入,再次getBeanA
2.6 第二次获取BeanA
我们在两次获取BeanA中间,2.2 设置正在创建BeanA,且三级缓存中放入了BeanA。
2.7 第二次从缓存中获取A
这一次,我们从一级和二级中都没有获取到BeanA,但是我们从三级缓存中获取到了一个回调函数—— getEarlyBeanReference,然后我们在获取缓存代码中执行 singletonObject = singletonFactory.getObject(),执行回调函数。
2.8 执行三级缓存回调
直接查询容器中有没有InstantiationAwareBeanPostProcessors的后置处理器。我们在文章开头假设中,假设A被切面C切中,即A需要被动态代理。
恰好AbstractAutoProxyCreator动态代理创建类实现了SmartInstantiationAwareBeanPostProcessor接口,实现了getEarlyBeanReference方法。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
//判读我们容器中是否有InstantiationAwareBeanPostProcessors类型的后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//获取我们所有的后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//判断我们的后置处理器是不是实现了SmartInstantiationAwareBeanPostProcessor接口
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
//进行强制转换
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//挨个调用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
... ... ... ...
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
... ... ... ...
}
2.9 B初始化
A 生成代理对象后放入二级缓存并返回。 B执行属性注入,开始初始化。
exposedObject = initializeBean(beanName, exposedObject, mbd);
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
... ... ... ...
//若我们的bean实现了XXXAware接口进行方法的回调
invokeAwareMethods(beanName, bean);
... ... ... ...
//调用我们的bean的后置处理器的postProcessorsBeforeInitialization方法
//@PostConstruct注解的方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
... ... ... ...
//调用初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
... ... ... ...
//调用我们bean的后置处理器的PostProcessorsAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获取我们容器中的所有的bean的后置处理器
for (BeanPostProcessor processor : getBeanPostProcessors()) {
/**
* 在这里是后置处理器的【第九次调用】 aop和事务都会在这里生存代理对象
*
* 【很重要】
* 我们AOP @EnableAspectJAutoProxy 为我们容器中导入了 AnnotationAwareAspectJAutoProxyCreator
* 我们事务注解@EnableTransactionManagement 为我们的容器导入了 InfrastructureAdvisorAutoProxyCreator
* 都是实现了我们的 BeanPostProcessor接口,InstantiationAwareBeanPostProcessor,
* 在这里实现的是BeanPostProcessor接口的postProcessAfterInitialization来生成我们的代理对象
*/
Object current = processor.postProcessAfterInitialization(result, beanName);
//若只有有一个返回null 那么直接返回原始的
if (current == null) {
return result;
}
result = current;
}
return result;
}
在B完成初始化后,最后执行了applyBeanPostProcessorsAfterInitialization,动态代理处理类也实现了该方法。也就是说,这里也可能返回代理类。
2.10 A完成初始化
B完成初始化后返回给A的属性注入,A完成属性注入后,接着完成初始化并返回。注意:由于A之前已经生成代理类,这里不会再重复创建。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
//获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 之前循环依赖创建的动态代理 如果是现在的bean 就不再创建,并且移除
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 该方法将会返回动态代理实例
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.11 A放入一级缓存
中间B也放入了一级缓存。再这里一起讲。 再2.2中,我们getSingleton方法中执行了回调方法完成Bean的创建,再执行完回调后,其实还有逻辑。
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
... ... ... ...
beforeSingletonCreation(beanName);
... ... ... ...
singletonObject = singletonFactory.getObject();
newSingleton = true;
... ... ... ...
if (newSingleton) {
// <5> 加入缓存中
addSingleton(beanName, singletonObject);
}
singletonFactory.getObject()执行回调,设置newSingleton = true,最后执行 addSingleton(beanName, singletonObject);
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//加入到单例缓存池中
this.singletonObjects.put(beanName, singletonObject);
//从三级缓存中移除(针对的不是处理循环依赖的)
this.singletonFactories.remove(beanName);
//从二级缓存中移除(循环依赖的时候 早期对象存在于二级缓存)
this.earlySingletonObjects.remove(beanName);
//用来记录保存已经处理的bean
this.registeredSingletons.add(beanName);
}
}
三. 常见问题
3.1. 二级缓存能不能解决循环依赖,为什么需要三级缓存
二级缓存可以解决循环依赖,在实例化后,属性注入和初始化前,将实例化后的Bean放入二级缓存池就可以。那为什么需要三级缓存呢?
网上很多答案是因为代理的原因,确实是其中重要的原因。但个人觉得还不够准确,因为二级缓存也可以直接放代理类进去。需要三级缓存个人比较赞成这个观点:
Bean的创建流程首先应该完成主体流程-即没有循环依赖的,没有代理的正常Bean创建流程。 在主体流程外提供扩展功能以满足其他需求。 单一职责的原则,循环依赖的解决放入专门解决循环依赖的地方——缓存,而不是在实例化后为了解决循环依赖+代理的问题,直接把代理生成的位置放在实例化后。
3.2. spring有没有解决构造函数的循环依赖
没有。 构造函数在实例化时调用。spring没有干预。
3.3.spring有没有解决多例下的循环依赖
没有。 多例没有缓存