spring_0">spring循环依赖深度源码解析
一,什么是循环依赖问题
简单来说循环依赖就是在spring容器中的两个Bean互相调用对方
在这里我们创建了两个对象A,B,在A中调用B,在B中调用A,这样就会产生循环依赖问题
public class A {private B b;public B getB() {return b;}public void setB(B b) {this.b = b;}
}
public class B {private A a;public A getA() {return a;}public void setA(A a) {this.a = a;}
}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="a" class="com.jixu.DTO.A"><property name="b" ref="b"></property></bean><bean id="b" class="com.jixu.DTO.B"><property name="a" ref="a"></property></bean>
</beans>
二,什么是三级缓存
三级缓存是咋spring的DefaultSingletenBeanRegister这个类当中
// 一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);// 二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
在这里最值得注意的是三级缓存,我们看一下它的类型Map<String, ObjectFactory<?>>,它的key的类型为 ObjectFactory<?>,我们进入源码来看一下这是个什么东西
// 函数式接口 --》 只有当调用getObject时候才会真正执行代码
@FunctionalInterface
public interface ObjectFactory<T> {/*** Return an instance (possibly shared or independent)* of the object managed by this factory.* @return the resulting instance* @throws BeansException in case of creation errors*/T getObject() throws BeansException;}
它使用了一个@FunctionalInterface也就是函数式接口,这样的话在三级缓存当中存放的就是Lambda表达式,而且只有当调用了其getObject方法的时候才会实际调用Lambda当中的代码
为什么spring要这样设计,提前暴露bean?那我们来想一个问题,如果对象是代理对象该怎么办,我们在创建的时候并不能知道该对象是代理对象还是普通对象,只有在实际调用的时候才能知道具体类型。那么函数式接口就可以完美解决这个问题,在实际调用的时候再使用getObject方法根据其类型实际创建对象。
三,全流程debug
在这里我们从AbstractApplicationContext这个类当中的refresh方法开始打断点
此时在我们的beanFactory当中也可以找到对应的三级缓存
按F8一直到preInstantiateSingletons这个方法中该方法是用来创建Bean的
在其中的beanNames当中就保存着我们所有注册的bean对象的beanDefinition信息,在这里就可以看到A,B对象,之后会循环A,B创建对象
在这里会进行一系列判断,之后会调用getBean方法,在getBean方法当中会调用doGetBean方法(通常以do开头的是实际执行的方法)
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}
在doGetBean当中会去判断对象在三级缓存当中是否存在
// 判断在三级缓存当中是否存在该对象
Object sharedInstance = getSingleton(beanName);
public Object getSingleton(String beanName) {return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lockObject singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;
}
如果不存在就会去调用其createBean方法创建Bean,快进到方法位置
// 创建Bean实例
if (mbd.isSingleton()) {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;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
在这里会进行一个判断,判断是否为单列对象,通过getSingleton方法传入bean名称与lambda表达式回调
createBean方法。在其createbean方法中会调用doCreateBean方法执行具体的实例化及属性赋值流程
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 创建通过反射创建对象
if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取到对象
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;
}
在doCreateBean当中会提前暴露对象,通过反射创建对象实例,其属性赋值为空。将将key=bean名称,value=lambda表达式加入三级缓存当中
这个方法的主要作用是在bean的生命周期中提供一个早期访问点,允许某些特定的处理或操作在bean完全初始化之前进行。这在需要对bean进行特殊处理,或者在bean初始化过程中需要引用同一bean的早期状态时非常有用。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;
}
调用其populateBean方法为A的属性进行赋值
在这里如果属性值为另一个Bean的引用时其值的类型为runTimeReference
循环所有属性进行赋值判断其类型是否为runTimeReference如果是则调用其getBean方法获取对象
在doGetBean当中就会尝试获取B的Bean,如果Bean不存在则创建B和上述流程一样
最后将B的lambda加入到三级缓存当中,调用populateBean方法赋值属性
此时B中需要注入A
此时在三级缓存当中就可以查询到Bean信息,之后会调用其getObject方法回调函数
// 从单例池当中获取对象
Object singletonObject = this.singletonObjects.get(beanName);
// 如果单例池当中不存在,且对象正在创建过程中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {// 从二级缓存当中获取对象singletonObject = this.earlySingletonObjects.get(beanName);// 如果二级缓存中不存在if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton lock// 再次检查singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {// 从三级缓存当中获取到对应的lambda表达式ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 调用其getObject方法singletonObject = singletonFactory.getObject();// 加入二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 从三级缓存当中删除this.singletonFactories.remove(beanName);}}}}
在这里将bean赋值给了exposedObject这也就是所谓的提前暴露对象, 通过该方法可以判断出是否有beanPostProcesser的增强,也就是是否为代理对象对其进行代理,如果不是则返回普通对象
此时就生成了A的半成品对象,并加入了二级缓存,之后对属性值赋值
执行完毕后将B对象加入一级缓存,此时B的完整Bean对象已经生成
protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
}
之后将B注入给A,将A对象加入一级缓存移除其二级缓存的数据