Spring源碼閱讀-BeanFactory-對象建立過程

1 getBean

上一節只是加載配置,並把文件內容映射到BeanDefinition中,真正的建立對象跟依賴注入是在getBean中處理的,這裏實際上就是根據BeanDefinition用反射建立對象及其依賴對象,只不過spring裏面處理的比較複雜,這裏面的每一步都有不少邏輯處理,而且在這先後作了不少的異常的判斷校驗。java

仍是以XmlBeanFactory跟蹤代碼看一下getBean流程,最終進入到AbstractBeanFactory的doGetBean方法:spring

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,
		boolean typeCheckOnly) throws BeansException {
	//1 去掉工廠bean的前綴& 並找到alias對應的名稱
	final String beanName = transformedBeanName(name);
	Object bean;
	// Eagerly check singleton cache for manually registered singletons.
	//2 先從緩存中獲取
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		if (logger.isDebugEnabled()) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				logger.debug("Returning eagerly cached instance of singleton bean '" + beanName
						+ "' that is not fully initialized yet - a consequence of a circular reference");
			} else {
				logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}
		//若是是bean工廠,則建立對象
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	else {
		// Fail if we're already creating this bean instance: We're assumably within a circular reference.
		//3 在原形狀況下建立循環依賴就會報錯
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		//4 Check if bean definition exists in this factory.
		BeanFactory parentBeanFactory = getParentBeanFactory();
		//若是存在父bean工廠而且沒有配置該bean,則從父bean工廠建立
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			String nameToLookup = originalBeanName(name);
			//遞歸調用getBean
			if (args != null) {
				// Delegation to parent with explicit args.
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			} else {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}
		try {
			//5 轉換BeanDefinition
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			//6 depends-on標籤
			// Guarantee initialization of beans that the current bean depends on.
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) {
					if (isDependent(beanName, dependsOnBean)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean
										+ "'");
					}
					registerDependentBean(dependsOnBean, beanName);
					//遞歸調用
					getBean(dependsOnBean);
				}
			}
			//7 不一樣scope狀況下建立對象
			// Singleton狀況
			// Create bean instance.
			if (mbd.isSingleton()) {
				//getSingleton有單例的控制, 防止前面已經建立過該對象,若是沒建立過該對象最終也是調用createBean
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					@Override
					public Object getObject() throws BeansException {
						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;
						}
					}
				});
				//8 獲取最終的對象
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}
			//prototype狀況
			else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				} finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}
			//其餘狀況
			else {
				String scopeName = mbd.getScope();
				final Scope scope = this.scopes.get(scopeName);
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
				}
				try {
					Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							} finally {
								afterPrototypeCreation(beanName);
							}
						}
					});
					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				} catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName,
							"Scope '" + scopeName + "' is not active for the current thread; "
									+ "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
							ex);
				}
			}
		} catch (BeansException ex) {
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
	}
	//9 類型轉換
	// Check if required type matches the type of the actual bean instance.
	if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
		try {
			return getTypeConverter().convertIfNecessary(bean, requiredType);
		} catch (TypeMismatchException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to convert bean '" + name + "' to required type ["
						+ ClassUtils.getQualifiedName(requiredType) + "]", ex);
			}
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
	}
	return (T) bean;
}
  1. 先把傳人的name轉變成真實的對象名稱beanName: 傳人的name稱多是別名或者工廠名(工廠名前綴爲&)
  2. 用beanName到緩存裏獲取單例對象,若是爲空則走下面流程,這步是針對單例對象的,這裏有三層緩存(爲了解決循環依賴,後面單獨敘述,這裏主要看主流程,不然會繞進去)。
  3. 原型依賴檢查,循環依賴只有在單例狀況下可用,原型狀況下向上拋異常
  4. 若是BeanDefinitionMap中沒有對應的bean,則到parentBeanFactory去尋找
  5. 若是上面都沒獲取到對象,則用beanName獲取BeanDefinition轉成RootBeanDefinition對象,後面不一樣類型的scope都是根據RootBeanDefinition建立的。
  6. 先建立BeanDefinition的dependsON對象(bean標籤的depends-on屬性,depends-on標籤不能循環依賴)
  7. 根據bean的scope走不一樣的建立流程,針對不一樣scope作了不一樣的控制,好比:singleton模式經過getSingleton方法,這個裏面建立對象時會先校驗緩存是否已經存在該對象,prototype模式直接建立對象,其餘類型的則能夠經過自定義Scope來實現邏輯控制,設想一下若是把對象放到第三方緩存中則可在這邊自定義一個Scope。最終bean的構造委託給了createBean,createBean方法比較複雜,下面單獨看。
  8. 上面獲取到的對象最終都須要再次校驗一下,由於獲取的對象也多是個工廠,這裏校驗的方法就是getObjectForBeanInstance
  9. 用TypeConverter轉成最終須要的類型。

時序圖以下:緩存

2 createBean

上面第7步,建立對象委託給了createBean,createBean中作一下初始化確認就把建立對象委託給了doCreateBean,doCreateBean核心代碼以下:app

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		//1. 建立對象
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
	Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

	//...省略

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		//2. 填充對象   這個裏面解析了依賴的bean
		populateBean(beanName, mbd, instanceWrapper);
		if (exposedObject != null) {
			//3. 初始化方法
			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);
		}
	}

	//...省略

	// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	} catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature",
				ex);
	}

	return exposedObject;
}

這裏分爲三個核心過程:ide

  1. 先建立bean,
  2. 而後把填充bean的屬性,這個裏面就是解析了依賴對象,
  3. 最後調用initializeBean初始化bean.

這三部分裏面都比較複雜,後面有時間再看,看一下createBean的時序圖:ui

相關文章
相關標籤/搜索