Spring源碼之Spring是怎麼創建Bean的?

在首次啓動容器的時候,必然會進入CreateBean,所以這裏直接採用DeBUG的方式追蹤源碼。

啓動Spring容器之前在方法上打上斷點。
在這裏插入圖片描述

調試出來自己認識的Bean
在這裏插入圖片描述
step into
在這裏插入圖片描述
創建Bean的主要做以下幾件事情。

  1. Bean類型的解析
  2. 處理方法的覆蓋
  3. Bean實例化之前的後置處理
  4. doCreateBean
    到下一步
    獲取這個Bean的BeanDefiniton實例
    在這裏插入圖片描述
    獲取這個BeanDefinition對用的Bean的class對象 ,驗證需要重寫的方法。
// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}

如果Bean配置了前置或者後置處理器,則進入相關邏輯的處理。

@Nullable
	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;
	}

如果配置後置 處理器,那麼就會直接返回經過後置處理包裝的Bean.
如果沒有配置,則會進入自己創建的邏輯。

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//這個 方法就是解析Bean創建錢的和創建後的後置處理器。
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
try {
//自己創建Bean實例的方法。
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}

doCreateBean

doCreateBean的具體邏輯如下 :
1.通過事先配置好 的工廠方法 ,創建一個沒有屬性值的Bean實例。
2.通過BeanDefinition的 後置處理器來處理Bean的屬性,其中就包括記錄@Autowired和@Value的屬性。
3.是否允許提前暴露。(即是單例模式,允許將還沒有給屬性賦值的Bean給暴露在外。)
4.填充屬性(自動注入)
5.初始化操作 。
6.視情況註冊銷燬邏輯。
7.返回創建好的實例 。

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

		// 定義了一個Bean的包裝類,可以獲取修改Bean的屬性
		BeanWrapper instanceWrapper = null;
		//是單例
		if (mbd.isSingleton()) {
		//從包裝類緩存中嘗試獲取,
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		//如果沒有獲取到,就自行創建包裝類
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//從包裝類中獲取Bean實例
		final Object bean = instanceWrapper.getWrappedInstance();
				//從包裝類中獲取Bean類型
		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 {
				//對自動注入和@value的屬性做處理
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

	//是否允許提前暴露
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			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) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						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 " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

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

		return exposedObject;
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章