1. 程式人生 > >【Spring原始碼閱讀】 preInstantiateSingletons方法分析,單例Bean獲取/例項化流程

【Spring原始碼閱讀】 preInstantiateSingletons方法分析,單例Bean獲取/例項化流程

在初始化ClassPathXmlApplicatonContext過程中,核心初始化邏輯在AbstractApplicationContext的refresh函式中:

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException已成
		prepareRefresh();

		// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 設定類載入器,spel解析器,屬性編輯解析器等,忽略特定介面的依賴註冊(在特定時刻相關Bean再完成注入),註冊一些系統Bean供依賴注入使用。 prepareBeanFactory(beanFactory); try { // BeanFactory建立完的後置處理。當前為空實現,供子類拓展
postProcessBeanFactory(beanFactory); // 呼叫BeanFacotry的相關後置處理器,如果實現了Order相關介面,會先進行排序。 invokeBeanFactoryPostProcessors(beanFactory); // 註冊相關BeanPostProcessor,供Bean生成前後呼叫。 registerBeanPostProcessors(beanFactory); // 初始化國際化資訊源 initMessageSource(); // 初始化Spring相關上下文時間廣播器 initApplicationEventMulticaster
(); // 模版方法供子類實現,用於初始化一些特殊Bean配置等 onRefresh(); // 註冊實現了ApplicationListener介面的事件監聽器,用於後續廣播器廣播事件 registerListeners(); // BeanFactory初始化完成時呼叫,初始ConversionService Bean,凍結beanFactory配置,並開始建立BeanFactory中所有非懶載入的單例Bean finishBeanFactoryInitialization(beanFactory); // 初始化Lifecycle處理器,呼叫onRefresh方法,廣播ContextRefreshedEvent。 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }

其中有一行程式碼,呼叫了finishBeanFactoryInitialization(beanFactory)。在這一步之前,已經完成了BeanFactory物件初始化、xml配置檔案解析成BeanDefinition、BeanPostProcessor初始化與註冊等操作。
而在完成BeanFactory初始化之時,會初始化容器內所有單例非懶載入物件,供後續業務邏輯進行依賴注入等使用,具體實現在finishBeanFactoryInitialization(beanFactory)內部的最後一行程式碼:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	//…… 省略前面程式碼

	// 預例項化所有非懶載入單例Bean
	beanFactory.preInstantiateSingletons();
}

具體的preInstantiateSingletons實現如下:

public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isInfoEnabled()) {
		this.logger.info("Pre-instantiating singletons in " + this);
	}

	List<String> beanNames;
	synchronized (this.beanDefinitionMap) {
		// 獲取容器內載入的所有BeanDefinition
		beanNames = new ArrayList<String>(this.beanDefinitionNames);
	}

	// 遍歷初始化所有非懶載入單例Bean
	for (String beanName : beanNames) {
	    // Bean定義公共的抽象類是AbstractBeanDefinition,普通的Bean在Spring載入Bean定義的時候,例項化出來的是GenericBeanDefinition
	    // 而Spring上下文包括例項化所有Bean用的AbstractBeanDefinition是RootBeanDefinition
	    // 這時候就使用getMergedLocalBeanDefinition方法做了一次轉化,將非RootBeanDefinition轉換為RootBeanDefinition以供後續操作。
	    // 注意如果當前BeanDefinition存在父BeanDefinition,會基於父BeanDefinition生成一個RootBeanDefinition,然後再將呼叫OverrideFrom子BeanDefinition的相關屬性覆寫進去。
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		// 如果Bean不是抽象的,是單例的,不是懶載入的,則開始建立單例物件通過呼叫getBean(beanName)方法初始化
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
		    // 判斷當前Bean是否實現了FactoryBean介面,如果實現了,判斷是否要立即初始化
		    // 判斷是否需要立即初始化,根據Bean是否實現了SmartFactoryBean並且重寫的內部方法isEagerInit放回true
			if (isFactoryBean(beanName)) {
				final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
						public Boolean run() {
							return ((SmartFactoryBean<?>) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean<?>) factory).isEagerInit());
				}
				if (isEagerInit) {
					getBean(beanName);
				}
			}
			else {
				getBean(beanName);
			}
		}
	}
}
// 具體getBean函式實現如下所示:
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

/*
進一步呼叫瞭如下方法,其中有引數:
requiredType=null: 一般情況用不到,如果獲取到的字串,但requiredType是Integer,會在最後進行型別轉換。
args=null: 在獲取prototype物件時傳入,用來初始化原型物件
typeCheckOnly=false: 如果為false,會將Bean標誌為已建立,記錄在alreadyCreated變數中。
*/
protected <T> T doGetBean(
		final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
		throws BeansException {
    // 如果是FactoryBean,會去掉Bean開頭的&符號
    // 可能存在傳入別名且別名存在多重對映的情況,這裡會返回最終的名字,如存在多層別名對映A->B->C->D,傳入D,最終會返回A
	final String beanName = transformedBeanName(name);
	Object bean;

	// 這裡先嚐試從快取中獲取,獲取不到再走後面建立的流程
	// 獲取到有兩種情況,一種是Bean建立完成儲存到最終的快取中。
	// 另一種是未建立完成,但先預存到一個單獨的快取中,這種是針對可能存在迴圈引用的情況的處理。
	// 如A引用B,B又引用了A,因而在初始化A時,A會先呼叫建構函式創建出一個例項,在依賴注入B之前,現將A例項快取起來
	// 然後在初始化A時,依賴注入階段,會觸發初始化B,B建立後需要依賴注入A時,先從快取中獲取A(這個時候的A是不完整的),避免迴圈依賴的問題出現。
	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 + "'");
			}
		}
		//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	else {
		// 原型物件不允許迴圈建立,如果是原型物件則拋異常
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// 如果存在父容器,且Bean在父容器中有定義,則通過父容器返回
		BeanFactory parentBeanFactory = getParentBeanFactory();
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			String nameToLookup = originalBeanName(name);
			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 {
		    // 根據名字獲取合併過的對應的RootBeanDefinition
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			// 檢查mbd是否為抽象的或mbd為單例,但存在args的情況(args只有初始化原型物件才允許存在)
			checkMergedBeanDefinition(mbd, beanName, args);

			// 確保當前Bean依賴的相關Bean先完成初始化工作
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) {
					getBean(dependsOnBean);
					registerDependentBean(dependsOnBean, beanName);
				}
			}

			// 前面獲取失敗,開始建立
			if (mbd.isSingleton()) {
			    // 會先嚐試從快取中獲取,獲取失敗就通過ObjectFactory的createBean方法建立
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					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;
						}
					}
				});
				//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

			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);
				}
				//這裡主要處理實現了FactoryBean的情況,需要呼叫重寫的getObject()方法來獲取實際的Bean例項。
				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>() {
						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;
		}
	}

	// 檢查是否為要求的型別,如果不是則嘗試進行型別轉換
	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;
}

getSingleton的方法的實現在父類DefaultSingletonBeanRegistry中

// 實現如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "'beanName' must not be null");
	synchronized (this.singletonObjects) {
	    //雙重判定從快取中獲取
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			// 建立前置檢查,預設實現是記錄當前beanName正在註冊中
			beforeSingletonCreation(beanName);
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<Exception>();
			}
			try {
			    // 呼叫簽名定義的內部類進行建立,內部呼叫了createBean(String beanName, RootBeanDefinition mbd, Object[] args)
				singletonObject = singletonFactory.getObject();
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				// 建立前置檢查,預設實現是移除當前beanName正在註冊狀態的記錄
				afterSingletonCreation(beanName);
			}
			addSingleton(beanName, singletonObject);
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}
}

createBean方法位於AbstractAutowireCapableBeanFactory中,具體實現如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	// 確保對應BeanClass完成解析,具體表現是進行了ClassLoder.loadClass或Class.forName完成了類載入
	resolveBeanClass(mbd, beanName);

	
	try {
	    // 準備方法覆蓋,主要為lookup-method,replace-method等配置準備
		mbd.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// 供特定後置處理器拓展,如果直接生成了一個Bean,就直接返回不走正常建立流程。
		// 具體邏輯是判斷當前Spring容器是否註冊了實現了InstantiationAwareBeanPostProcessor介面的後置處理器
		// 如果有,則依次呼叫其中的applyBeanPostProcessorsBeforeInstantiation方法,如果中間任意一個方法返回不為null,直接結束呼叫。
		// 然後依次所有註冊的BeanPostProcessor的postProcessAfterInitialization方法(同樣如果任意一次返回不為null,即終止呼叫。
		Object bean = resolveBeforeInstantiation(beanName, mbd);
		// 如果不為空,說明提前生成了例項,直接返回
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

    // 具體建立Bean邏輯
	Object beanInstance = doCreateBean(beanName, mbd, args);
	if (logger.isDebugEnabled()) {
		logger.debug("Finished creating instance of bean '" + beanName + "'");
	}
	return beanInstance;
}

具體建立Bean的邏輯如下所示:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    // BeanWrapper封裝了具體的Bean例項,然後可以很方便地通過呼叫getPropertyValue和setPropertyValue等方法反射讀寫Bean的具體屬性
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	    // 先嚐試從快取中取
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	    // 呼叫構造方法建立一個空例項物件,並用BeanWrapper進行包裝
		instanceWrapper = createBeanInstance(beanName, mbd, args); 
	}
	final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
	Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null)