【Spring源碼解析】Bean循環依賴

1.什麼是循環依賴
....
2.Spring Bean循環依賴
2.1 不能解決:構造器注入循環依賴;prototype模式field屬性注入循環依賴
2.2 能解決:ngleton模式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. 參考
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章