- 请你解释下spring中的三级缓存
- 三级缓存分别是什么?三个map有什么异同?
- singletonObjects(一级缓存)
存放已经经历了完整生命周期的Bean对象 - earlySingletonObjects(二级缓存)
存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整) - singletonFactories(三级缓存)
存放生成Bean的工厂
- 什么是循环依赖, 请你谈谈?看过spring源码吗?一般我们说的spring容器是什么?
- 如何检测存在循环依赖?实际开发中见过循环依赖的异常吗?
- 多例的情况下, 循环依赖问题为什么无法解决?
spring循环以来的3个Map和4大方法
// 3个Map
singletonObjects, singletonFactories, earlySingletonObjects
// 4大方法
getSingleton, doCreateBean, populateBean, addSingleton
// 注意这里
Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
第一层singletonObjects存放的是已经初始化好的bean
第二层earlySingletonObjects存放的是实例化了的,但是未初始化的bean
第三层singletonFactories存放的是FactoryBean, 加入A类实现了FactoryBean,那么依赖注入的时候不是A类,而是A类产生的bean
总体的大致流程
- A创建过程中需要B,于是把自己放到三级缓存里,去实例化B
- B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A。然后把A放到了二级缓存里面,并删除三级缓存里的A
- B顺利初始化完毕,把自己放到一级缓存里面(此时B里面的A依旧是创建中的状态),然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建。并将A自己放到一级缓存里面
spring循环依赖的断点
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
其中断点打在ClassPathXmlApplicationContext的refresh()这一行
- 断点打在
org.springframework.context.support.AbstractApplicationContext#refresh
中的finishBeanFactoryInitialization(beanFactory);
这个方法 -
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
断点打在beanFactory.preInstantiateSingletons();
这一行 -
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
断点打在getBean(beanName);
这一行 -
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
->org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
也就是说从getBean到doGetBean -
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
断点打在Object sharedInstance = getSingleton(beanName);
这一行 -
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
断点打在这行
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
- 断点打在
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
的singletonObject = singletonFactory.getObject();
这一行 - 断点打在
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
的return createBean(beanName, mbd, args);
这一行 - 断点打在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
的Object beanInstance = doCreateBean(beanName, mbdToUse, args);
这一行
至此,到了第二个重要方法doCreateBean() - 断点打在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
这一行。
注意,这一行表示要将A放到三级缓存里面了 - 断点打在
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory
的this.singletonFactories.put(beanName, singletonFactory);
这一行。
这一行表示,将A和生产它的bean工厂放到三级缓存里 - 断点打在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
的populateBean(beanName, mbd, instanceWrapper);
这一行。
表示开始填充A的属性。至此,到了第三个重要方法populateBean() - 进入上面的populateBean方法,断点打在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
的applyPropertyValues(beanName, mbd, bw, pvs);
这一行 - 进入上面的applyPropertyValues方法,断点打在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues
的Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
这一行 - 进入上面的resolveValueIfNecessary方法,断点打在
return resolveReference(argName, ref);
这行 - 进入上面的resolveReference方法,断点打在
bean = this.beanFactory.getBean(resolvedName);
这一行。
至此回到了第6步中的doGetBean方法 - 接下来的步骤与上面类似,在创建B的过程中我们发现需要属性A, 断点来到
org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference
的bean = this.beanFactory.getBean(resolvedName);
这一行,开始寻找属性A - 断点打在
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
的Object sharedInstance = getSingleton(beanName);
这一行,进入该方法 - 断点打在
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
的ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
这一行。在这里,从三级缓存中找到了A,于是将A放到二级缓存中,并从三级缓存中移除 - 在上一步之后,B中的A属性填充完毕了, 返回到
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
的populateBean(beanName, mbd, instanceWrapper);
的下一行exposedObject = initializeBean(beanName, exposedObject, mbd);
,断点打在这里。 - 断点打在
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
的addSingleton(beanName, singletonObject);
这一行,这也是上面说的4大方法中的一个 - 进入这个方法,这个方法将b加入到一级缓存中,并在二级缓存和三级缓存中移除
- 返回到
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
的populateBean(beanName, mbd, instanceWrapper);
的下一行exposedObject = initializeBean(beanName, exposedObject, mbd);
,断点打在这里。这里,A中的b属性填充完毕了 - 断点打在
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
的addSingleton(beanName, singletonObject);
这一行。进入这个方法,在这里,将a放到一级缓存,并将它从二级和三级缓存中删除
来张图片看一下整体流程吧


网友评论