什么是循环依赖:简单来说就是在spring容器中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 B() {
}
public B(A a) {
this.a = a;
}
public A getC() {
return a;
}
}
什么情况下spring能够解决循环依赖
①出现循环依赖的Bean必须要是单例
②依赖注入的方式需要是set方式注入 (但是也有特殊情况,假设你仅仅获取A实例,那么B类中可以是构造注入。原因在于b实例化是在填充属性时进行解决的,如果没有set进行属性赋值 则不会进行B的实例化。但B类实例化时已经存在A的实例,可以直接引用。但在直接获取B实例时报错)当然如果两个都使用set注入更好
直接获取b实例 报错原因是 A类没办法进行set注入,那么不会再填充属性是进行实例化。
如果B类中也是set注入则下面代码不会报错
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
xmlBeanFactory.getBean("b");
源码查看循环依赖解决过程
首先xml配置
<bean name="a" class="com.gl.pojo.A">
<property name="b" ref="b"></property>
</bean>
<bean name="b" class="com.gl.pojo.B">
<constructor-arg ref="a" name="a"/>
</bean>
test演示
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
A a = (A)xmlBeanFactory.getBean("a");
System.out.println(a);
System.out.println(a.getB());
源码:
三级缓存
//一级缓存 存储初始化后的完整实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存 存储实例
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
//三级缓存 存储bean工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
核心方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
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) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//放到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
一开始三个缓存都是空的
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
这个addSingletonFactory() 方法第一次将 beanFactoy存到三级缓存。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 后置处理合并后的BeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 为了解决循环依赖提前缓存单例创建工厂
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//主动缓存单例,以便能够解析循环引用,即使是由BeanFactoryAware等生命周期接口触发时也是如此。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 循环依赖-添加到三级缓存 后续循环依赖 调用getEarlyBeanReference 方法获取实例
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//初始化bean实例。
Object exposedObject = bean;
try {
// 属性填充
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
//获取的到的实例
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
//注册其DisposableBean接口和/或给定的destroy方法,以便在工厂关闭时调用(如果适用)。只适用于单例。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
之后进行属性填充 发现B实例不存在将创建B实例 核心方法 resolveReference(argName, ref)
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
//我们必须检查每个值,看它是否需要运行时引用
// to another bean to be resolved.
//到另一个待解析的bean。
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//所依赖的bean是一个运行时引用 需要进行解析引用
return resolveReference(argName, ref);
}
}
获取 b实例 bean = this.beanFactory.getBean(resolvedName); 类似于xmlBeanFactory.getBean(“a”); 只不过现在resolvedName 是b ,开始执行b的doCreateBean 。重复了上面的过程。再b实例化后填充a属性,此时获取a实例将会执行getSingleton方法,此时三级缓存存在a的beanFactory。
singletonObject = singletonFactory.getObject();
//放到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存移除
this.singletonFactories.remove(beanName);
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
Class<?> beanType = ref.getBeanType();
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean " + ref +
" in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
}
else {
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
}
}
else {
String resolvedName;
if (beanType != null) {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
}
else {
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
//从bean工厂获取bean
bean = this.beanFactory.getBean(resolvedName);
}
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
b实例的属性填充完成之后执行初始化后存入到一级缓存。 以下是简化代码。之后a继续填充b属性完成a的初始化。
//创建bean实例 调用 singletonFactory 的 实现 createBean(beanName, mbd, args);
singletonObject = singletonFactory.getObject();
newSingleton = true;
//初始化后执行
// 将初始化后的bean放到一级缓存 添加到单例池 singletonObjects 和 按注册顺序 的bean名称 registeredSingletons
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
return singletonObject;
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将初始化的bean放到一级缓存
this.singletonObjects.put(beanName, singletonObject);
//从三级缓存清除
this.singletonFactories.remove(beanName);
//从二级缓存清除
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
大致流程
上述我们看到了三级缓存在整个循环依赖中的使用,如果没有循环依赖,我们是可以省略三级缓存的。 只用一级缓存就可以进行单例的实现,
其实发现其实使用二级缓存也能实现循环依赖的解决。即在a实例化后进行缓存,然后b初始化时使用。其实是没有问题的。之所以使用三级缓存时在aop代理对象中使用。这将在下一篇讲解。