Spring Ioc源碼分析 之 Bean的加載(四):createBean()

上一篇文章Spring Ioc 之 Bean的加載(三):各個 scope 的 Bean 建立 咱們分析了各個做用域Bean的建立大致流程。這篇文章咱們來分析如下建立Bean的關鍵方法 createBean()java

createBean()

代碼:spring

//AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	//判斷須要建立的Bean是否能夠實例化,便是否能夠經過當前的類加載器加載
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	//校驗和準備Bean中的方法覆蓋
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		//若是Bean配置了初始化前和初始化後的處理器,則試圖返回一個須要建立Bean的代理對象
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		//建立Bean的入口
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException ex) {
		// A previously detected exception with proper bean creation context already...
		throw ex;
	}
	catch (ImplicitlyAppearedSingletonException ex) {
		// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
	}
複製代碼

這段代碼分爲如下幾個步驟:緩存

  1. 判斷須要建立的Bean是否能夠實例化,便是否能夠經過當前的類加載器加載app

  2. 校驗和準備Bean中的方法注入ide

  3. 若是Bean配置了初始化前和初始化後的處理器,則試圖返回一個須要建立Bean的代理對象函數

  4. 建立Beanpost

第1步

主要是獲取bean的class,並設置到BeanDefinition中this

第2步

主要是處理方法注入
代碼:spa

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	//檢測是否存在方法注入,並循環預處理方法注入
	if (hasMethodOverrides()) {
		Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
		        //遍歷處理
			for (MethodOverride mo : overrides) {
				prepareMethodOverride(mo);
			}
		}
	}
	}
複製代碼

prepareMethodOverride(mo):debug

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        // 統計注入的方法個數 
	int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
	if (count == 0) {
		throw new BeanDefinitionValidationException(
				"Invalid method override: no method with name '" + mo.getMethodName() +
				"' on class [" + getBeanClassName() + "]");
	}
        // 若是爲1,則將注入方法標記爲未重載
	// 注意:當有多個重載方法時,爲了肯定調用哪一個具體的方法,Spring對重載方法的參數解析是很複雜的
	// 因此,若是注入方法沒有被重載這裏就將其標記,省去了對方法參數的解析過程,直接調用便可
	else if (count == 1) {
		// Mark override as not overloaded, to avoid the overhead of arg type checking.
		mo.setOverloaded(false);
	}
	}
複製代碼

代碼讀到這裏,你們可能有疑問,從代碼上看明明是處理的方法重載,可是爲何處理的是方法注入呢?並且若是咱們在bean裏設置幾個方法重載的話,hasMethodOverrides()方法返回的是false。若是咱們打開 AbstractBeanDefinition 類的 hasMethodOverrides() 方法,就能打消咱們以前的疑問。

public boolean hasMethodOverrides() {
		return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
	}
複製代碼

其中methodOverrides是作什麼的呢?經過類名AbstractBeanDefinition咱們能夠發現,該類是BeanDefinition的一個子類,那麼它保存的應該是咱們解析到的beanDefinition,spring在解析配置文件的時候,若是發現配置了replace-method或者lookup-method那麼,就會對應的標籤解析,並存入到 AbstractBeanDefinition 的 methodOverrides 屬性中,那麼當bean實例化的時候,若是檢測到了methodOverrides屬性不爲空,則動態的爲當前bean生成代理並使用相應的攔截器對bean作處理,這裏你們只要把概念搞清楚便可。

第3步

主要是對bean前置後置處理器的處理,給 BeanPostProcessors 後置處理器一個返回代理對象的機會
詳細代碼:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
	}
複製代碼

若是代理對象不爲空,則直接返回代理對象,這一步驟有很是重要的做用,Spring 後續實現 AOP 就是基於這個地方判斷的。
這個方法核心就在於 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 兩個方法,before 爲實例化前的後處理器應用,after 爲實例化後的後處理器應用。

第4步

doCreateBean()
建立Bean

//真正建立Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

	// Instantiate the bean.
	//BeanWrapper是對Bean的包裝,其接口中所定義的功能很簡單包括設置獲取被包裝的對象,獲取被包裝bean的屬性描述器
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	        //單例模式,刪除factoryBean緩存
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	        //使用合適的實例化策略來建立Bean:工廠方法、構造函數自動注入、簡單初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	//從包裝類中獲取實例化的Bean
	final Object bean = instanceWrapper.getWrappedInstance();
	//獲取實例化對象的類型
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// Allow post-processors to modify the merged bean definition.
	//檢查是否有後置處理
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
			        //調用PostProcessor後置處理器,修改 BeanDefinition
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	// 解決單例模式的循環依賴
	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, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	//Bean對象的初始化,依賴注入在此觸發
	//這個exposedObject在初始化完成以後返回做爲依賴注入完成後的Bean
	Object exposedObject = bean;
	try {
		//將Bean實例對象封裝,而且Bean定義中配置的屬性值賦值給實例對象
		populateBean(beanName, mbd, instanceWrapper);
		//初始化Bean對象
		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);
		}
	}

	if (earlySingletonExposure) {
		//獲取指定名稱的已註冊的單例模式Bean對象
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			//根據名稱獲取的已註冊的Bean和正在實例化的Bean是同一個
			if (exposedObject == bean) {
				//當前實例化的Bean初始化完成
				exposedObject = earlySingletonReference;
			}
			//當前Bean依賴其餘Bean,而且當發生循環引用時不容許新建立實例對象
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				//獲取當前Bean所依賴的其餘Bean
				for (String dependentBean : dependentBeans) {
					//對依賴Bean進行類型檢查
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	// Register bean as disposable.
	//註冊完成依賴注入的Bean
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
	}
複製代碼

代碼很長,不過別慌,咱們來按步驟分析一波

  1. 若是是單例模式,從factoryBeanInstanceCache 緩存中獲取BeanWrapper 實例對象並刪除緩存
  2. 調用 createBeanInstance() 實例化 bean
  3. 後置處理
  4. 單例模式的循環依賴處理
  5. 屬性填充
  6. 初始化 bean 實例對象
  7. 依賴檢查
  8. 註冊bean的銷燬方法

doCreateBean() 完成 bean 的建立和初始化工做,內容太多,比較複雜,這裏只列出大體流程,接下來咱們將分幾篇文章來分別闡述相關內容。

相關文章
相關標籤/搜索