1. 程式人生 > >spring學習-分步getBean方法(1)

spring學習-分步getBean方法(1)

所有spring在初始化完成BeanDefinition以後(預設使用的是GenericBeanDefinition)後。在使用spring容器裡的bean例項時,我們一般都是通過getBean方法實現的。例如

	private ClassPathXmlApplicationContext context;
	
	@Before
	public void setUp() throws Exception {
		context = new ClassPathXmlApplicationContext("classpath*:gg/spring/context.xml");
	}

	@Test
	public void testLoadBean() {
		//獲取spring的bean例項
		context.getBean("test1");
	}

其中ClassPathXmlApplicationContext的方法getBean,是呼叫了AbstractApplicationContext裡的getBean方法。而AbstractApplicationContext的getbean方法呼叫了beanFactory窗器是的getBean方法,此時的beanFactory是使用具體實現類是DefaultListableBeanFactory類,getBean方法是呼叫的父類AbstractBeanFactory的getBean實現
	public Object getBean(String name) throws BeansException {
		return getBeanFactory().getBean(name);
	}

AbstractBeanFactory的getBean方法程式碼如下,其中呼叫了doGetBean方法,引數為name:bean的名稱,

	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

protected <T> T doGetBean(final String name, final Class<T> requriedType, final Object[] args, boolean typeCheckOnly) {
		//生成beanName,如果是factorybean的name,去除factorybean的第一位標記&
		//判斷當前beanName是否是別名,如果是別名,取對應的真實的beanName
		final String beanName = transformedBeanName(name);
		Object bean;
		//獲取對應的已經建立的單例bean,這裡呼叫的是DefaultSingletonRegistry.getSingleton(beanName),實際呼叫的是DefaultSingletonRegistry.getSingleton(beanName, true)
		//其中DefaultSingletonRegistry.getSingleton(beanName, true)以下詳細說明
		Object shareInstance = getSingleton(beanName);

DefaultSingletonRegistry.getSingleton(beanName, true)說明
/**
	 * 此處方法用於spring處理迴圈依賴。A-->B,B-->C,C-->A,A中方法setB,B中方法setC,C中方法setA
	 * 建立A例項後初始化A的屬性,發現需要引用B,去建立B,建立B例項後初始化B的屬性時需要引用C,會去建立C例項後初始化C的屬性,此時的singletonsCurrentLyInCreation中包括A,B,C
	 * 此時C又引用了A,需要再次去建立A,而這時A只是生成物件,但A的還沒有真正建立完成,(if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))為true)
	 * 此時取A的依賴建立快取(earlySingletonObjects),還是沒有例項,預設是允許早期依賴建立(if (singletonObject == null && allowEarlyReference) == true)
	 * 這時去取A的建立工廠,singletonFactoryies中,是在A例項化後寫入一個簡單的依賴工廠類,可以參考方法AbstractAutowireCapableBeanFactory.doCreateBean方法,
	 * 這時通過依賴工廠得到的A的例項其他就是之前A建立的,但沒有初始化屬性的物件。
	 * 之後C的例項化完成-->B的例項化完成-->A的例項化完成。
	 * @param beanName
	 * @param allowEarlyReference
	 * @return
	 */
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//先從快取中獲取例項
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果級存中不存在,並且beanName是正在建立的beanName(singletonsCurrentlyInCreation,在建立例項時會寫入,說明有依賴迴圈依賴的情況)
		//isSingletonCurrentlyIncreation說明
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (singletonObject) {
				//查詢是否有依賴這個bean的例項
				singletonObject = this.earlySingletonObjects.get(beanName);
				//如果沒有並且允許迴圈依賴建立
				if (singletonObject == null && allowEarlyReference) {
					//找到建立這個bean的工廠類,並建立這個bean.同時放到早期的快取中,並移除這個建立工廠,不再建立,這個建立工廠只是簡單的返回之前例項的物件
					ObjectFactory objectFactory = this.singletonFactories.get(beanName);
					if (objectFactory != null) {
						singletonObject = objectFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT) ? singletonObject : null;
	}

AbstractAutowireCapableBeanFactory中的doCreateBean方法裡有以下內容,此處的addSinletonFactory是呼叫的DefaultSingletonRegistry的addSingletonFactory方法

//此處判斷當前的bean是否正在建立中,並且允許迴圈依賴,spring所有單例在建立過程中都會臨時存放一個依賴的建立工廠,當spring建立成功之後,會移除建立工廠類
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}
DefaultSingletonRegistry.addSingletonFactory方法實現如下
protected void addSingletonFactory(String beanName, ObjectFactory objectFactory) {
		Assert.notNull(objectFactory, "Object factory must not be null");
		synchronized (singletonObjects) {
			if (!singletonObjects.containsKey(beanName)) {
				//bean對應的建立工廠類
				this.singletonFactories.put(beanName, objectFactory);
				//移除存放的早期以來
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

此處有一個地方需要注意的是,spring在建立單例的依賴工廠時,會呼叫bean中的甩的的SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference對早期依賴的物件進行處理
	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
					if (exposedObject == null) {
						return exposedObject;
					}
				}
			}
		}
		return exposedObject;
	}