【Spring源码解析】Bean循环依赖

1.什么是循环依赖
....
2.Spring Bean循环依赖
2.1 不能解决:构造器注入循环依赖;
根本原因:Spring解决循环依赖依靠的是Bean的“中间态”这个概念,而这个中间态指的是已经实例化,但还没初始化的状态。
而构造器是完成实例化的东东,所以构造器的循环依赖无法解决~~~
加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决
2.2 prototype模式field属性注入循环依赖
2.3 能解决:singleton模式field属性注入(或setter方法注入)循环依赖
3.测试demo
3.1 spring-bean-circular-references.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="spring.circularreferences.A">
        <property name="b" ref="b" />
    </bean>
    <bean id="b" class="spring.circularreferences.B">
        <property name="a" ref="a" />
    </bean>
</beans>

3.2 CircularReferencesTest.java

public class CircularReferencesTest {
    
    @Test
    public void test01() {
        ClassPathResource resource = new ClassPathResource("spring-bean-circular-references.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(resource);
    
        A a = (A)factory.getBean("a");
        B b = (B)factory.getBean("b");
        Assert.assertEquals(a,b.getA());
        Assert.assertEquals(b,a.getB());
    }
}
  1. 源码部分解析
    4.1 三级缓存,参考DefaultSingletonBeanRegistry.java
/** 一级缓存:存放完全实例化属性赋值完成的Bean,直接可以使用 **/
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 三级缓存:singletonFactories,三级缓存,存放实例化完成的Bean工厂 **/
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 二级缓存:earlySingletonObjects,存放早期Bean的引用,尚未属性装配的Bean **/
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

4.2 流程

  • getBean(...); // AbstractBeanFactory类 198行
  • doGetBean(...) // AbstractBeanFactory类 239行
  • getSingleton(beanName) // AbstractBeanFactory类 246行
  • getSingleton(beanName,()->{...})// AbstractBeanFactory类 315行
  • singletonFactory.getObject();// AbstractBeanFactory类 222行
  • createBean();// AbstractAutowireCapableBeanFactory类 456行
  • doCreateBean()// AbstractAutowireCapableBeanFactory类 526行
  • addSingletonFactory()// AbstractAutowireCapableBeanFactory类 566行
  • populateBean()// AbstractAutowireCapableBeanFactory类 572行


4.3 实例化Bean

// Create bean instance. 实例化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);
}

4.4 getSingleton 获取实例对象

/**
 * Return the (raw) singleton object registered under the given name.
 * <p>Checks already instantiated singletons and also allows for an early
 * reference to a currently created singleton (resolving a circular reference).
 * @param beanName the name of the bean to look for
 * @param allowEarlyReference whether early references should be created or not
 * @return the registered singleton object, or {@code null} if none found
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//先从一级缓存中获取已经实例化属性赋值完成的Bean
	Object singletonObject = this.singletonObjects.get(beanName);
	//一级缓存不存在,并且Bean正处于创建的过程中
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			//从二级缓存中查询,获取Bean的早期引用,实例化完成但是未赋值完成的Bean
			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;
}

4.5 addSingletonFactory

	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * <p>To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
  1. 参考
原文地址:https://www.cnblogs.com/zendwang/p/spring-bean-circular-references.html