前置知识
- 只有单例模式下的bean会通过三级缓存提前暴露来解决循环依赖的问题。而非单例的bean每次获取都会重新创建,并不会放入三级缓存,所以多实例的bean循环依赖问题不能解决。
- 首先需要明白处于各个阶段的bean被放在哪里。在DefaultSingletonBeanRegistry类中
/** 一级缓存,存放经历完整生命周期的bean*/
private final Map singletonObjects = new ConcurrentHashMap(256);
/** 三级缓存,存放FactoryBean */
private final Map> singletonFactories = new HashMap>(16);
/** 二级缓存,存放刚刚创建出来还未进行属性赋值的bean */
private final Map earlySingletonObjects = new HashMap(16);
测试代码
public class ServiceAA {
public ServiceAA() {
System.out.println("AA已经创建");
}
private ServiceBB serviceBB;
public ServiceBB getServiceBB() {
return serviceBB;
}
public void setServiceBB(ServiceBB serviceBB) {
this.serviceBB = serviceBB;
}
}
public class ServiceBB {
public ServiceBB() {
System.out.println("BB已经创建");
}
private ServiceAA serviceAA;
public ServiceAA getServiceAA() {
return serviceAA;
}
public void setServiceAA(ServiceAA serviceAA) {
this.serviceAA = serviceAA;
}
}
流程
- 在上述代码中,ServiceAA 依赖于ServiceBB,同时ServiceBB也依赖于ServiceAA ,各个bean相互依赖,最终形成了闭环,那么spring是如何解决此问题的呢?
- 可以简单理解为spring创建bean分为两个步骤,第一步是创建原始bean,第二步就是对属性进行赋值和初始化等操作。
- 每次创建bean之前都会去缓存中查找是否有当前bean,因为是单例,只能有一个
- 当创建bean serviceAA后,会将其加入三级缓存中,然后需要填充bean的属性了
- 这时候发现需要依赖于bean serviceBB,接下来又去创建serviceBB。重复1-3的流程
- 这时候发现需要依赖于bean serviceAA,发现三级缓存中存在bean serviceAA,所以不需要重复创建。把bean serviceAA注入bean serviceBB
- 这个时候bean serviceBB创建好了,递归继续去为bean serviceAA进行属性赋值。闭环完成
源码
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
try {
//初始化剩下的单实例bean
finishBeanFactoryInitialization(beanFactory);
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//实例化单实例bean
beanFactory.preInstantiateSingletons();
}
@Override
public void preInstantiateSingletons() throws BeansException {
getBean(beanName);
}
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected T doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
//首先查询缓存中是否存在bean,当前为null
Object sharedInstance = getSingleton(beanName);
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//一级缓存中是否存在当前bean(serviceAA),此时为null
//isSingletonCurrentlyInCreation(beanName),当前bean是否被标记为
//正在创建,返回false,所以后续不执行,直接返回null
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
addSingleton(beanName, singletonObject);
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
protected void beforeSingletonCreation(String beanName) {
//将当前正在创建的bean serviceAA 标记为正在创建中,添加到集合singletonsCurrentlyInCreation中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
//开始真正的创建bean service AA
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
//用反射创建初始bean serviceAA,源码部分略过
instanceWrapper = createBeanInstance(beanName, mbd, args);
//当前为true
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//如果一级缓存中没有当前bean,就将当前bean放入三级缓存
addSingletonFactory(beanName, new ObjectFactory
protected void addSingletonFactory(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//将当前bean serviceAA放入三级缓存,key为beanname value为创建该bean的工厂
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
//获取当前bean sercieAA所有的属性
PropertyValues pvs = mbd.getPropertyValues();
//......对属性的解析等操作略过
//开始注入属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
//封装所有属性的集合,略过
List original;
for (PropertyValue pv : original) {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
//解析引用类型的属性
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
}
//应用属性过程略过
}
public Object resolveValueIfNecessary(Object argName, Object value) {
//判断是否是运行时bean引用
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//解析此引用 service BB
return resolveReference(argName, ref);
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
//开始递归调用getbean方法,当前bean为serviceBB
Object bean = this.beanFactory.getBean(refName);
}
- 此时serviceBB开始递归调用getBean()方法,开始重复上述流程,关注流程第五步。此时bean serviceBB实例化完成,并且开始为属性赋值,发现有一个属性为serviceAA。于是尝试获取serviceAA。
- 进入this.beanFactory.getBean()方法。进入doGetBean()方法。后进入getSingleton(String beanName, boolean allowEarlyReference)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//一级缓存中是否存在当前bean(serviceAA),此时为null
//isSingletonCurrentlyInCreation(beanName),当前bean是否被标记为
//正在创建,当前为true,进入判断
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//判断二级缓存中是否有bean serviceAA,当前返回null
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//通过beanname获得了之前在三级缓存中添加的创建serviceAA的工厂方法
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//此时singletonObject指向之前实例化完成的serviceAA对象
singletonObject = singletonFactory.getObject();
//将serviceAA添加到二级缓存中,并从三级缓存中删除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
- 此时serviceBB的属性赋值完毕,serviceBB的populateBean方法执行结束。其属性service AA指向还未执行完成populateBean()方法的bean serviceAA,等待后续的递归返回。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将serviceBB放入一级缓存
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
//从三级缓存,二级缓存中删除
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
- 此时serviceBB创建完毕。递归返回继续还未属性赋值完成的bean serviceAA。调用 addSingleton()方法,同上将bean serviceAA放入一级缓存
总结
欢迎关注公众号:前程有光,领取一线大厂Java面试题总结+各知识点学习思维导+一份300页pdf文档的Java核心知识点总结!