真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringIoc中Bean的加載實(shí)現(xiàn)方法

這篇文章主要講解了“Spring  Ioc中Bean的加載實(shí)現(xiàn)方法”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Spring  Ioc中Bean的加載實(shí)現(xiàn)方法”吧!

創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比秀英網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式秀英網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋秀英地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。

createBean()

代碼:

//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.
	//判斷需要?jiǎng)?chuàng)建的Bean是否可以實(shí)例化,即是否可以通過當(dāng)前的類加載器加載
	Class resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	//校驗(yàn)和準(zhǔn)備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配置了初始化前和初始化后的處理器,則試圖返回一個(gè)需要?jiǎng)?chuàng)建Bean的代理對(duì)象
		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 {
		//創(chuàng)建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);
	}
	}

這段代碼分為以下幾個(gè)步驟:

  1. 判斷需要?jiǎng)?chuàng)建的Bean是否可以實(shí)例化,即是否可以通過當(dāng)前的類加載器加載

  2. 校驗(yàn)和準(zhǔn)備Bean中的方法注入

  3. 如果Bean配置了初始化前和初始化后的處理器,則試圖返回一個(gè)需要?jiǎng)?chuàng)建Bean的代理對(duì)象

  4. 創(chuàng)建Bean

第1步

主要是獲取bean的class,并設(shè)置到BeanDefinition中

第2步

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

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	//檢測(cè)是否存在方法注入,并循環(huán)預(yù)處理方法注入
	if (hasMethodOverrides()) {
		Set overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
		        //遍歷處理
			for (MethodOverride mo : overrides) {
				prepareMethodOverride(mo);
			}
		}
	}
	}

prepareMethodOverride(mo):

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        // 統(tǒng)計(jì)注入的方法個(gè)數(shù)   
	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,則將注入方法標(biāo)記為未重載
	// 注意:當(dāng)有多個(gè)重載方法時(shí),為了確定調(diào)用哪個(gè)具體的方法,Spring對(duì)重載方法的參數(shù)解析是很復(fù)雜的
	// 所以,如果注入方法沒有被重載這里就將其標(biāo)記,省去了對(duì)方法參數(shù)的解析過程,直接調(diào)用即可
	else if (count == 1) {
		// Mark override as not overloaded, to avoid the overhead of arg type checking.
		mo.setOverloaded(false);
	}
	}

代碼讀到這里,大家可能有疑問,從代碼上看明明是處理的方法重載,但是為什么處理的是方法注入呢?而且如果我們?cè)赽ean里設(shè)置幾個(gè)方法重載的話,hasMethodOverrides()方法返回的是false。如果我們打開 AbstractBeanDefinition 類的 hasMethodOverrides() 方法,就能打消我們之前的疑問。

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

其中methodOverrides是做什么的呢?通過類名AbstractBeanDefinition我們可以發(fā)現(xiàn),該類是BeanDefinition的一個(gè)子類,那么它保存的應(yīng)該是我們解析到的beanDefinition,spring在解析配置文件的時(shí)候,如果發(fā)現(xiàn)配置了replace-method或者lookup-method那么,就會(huì)對(duì)應(yīng)的標(biāo)簽解析,并存入到 AbstractBeanDefinition 的 methodOverrides 屬性中,那么當(dāng)bean實(shí)例化的時(shí)候,如果檢測(cè)到了methodOverrides屬性不為空,則動(dòng)態(tài)的為當(dāng)前bean生成代理并使用相應(yīng)的攔截器對(duì)bean做處理,這里大家只要把概念搞清楚即可。

第3步

主要是對(duì)bean前置后置處理器的處理,給 BeanPostProcessors 后置處理器一個(gè)返回代理對(duì)象的機(jī)會(huì)
詳細(xì)代碼:

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

如果代理對(duì)象不為空,則直接返回代理對(duì)象,這一步驟有非常重要的作用,Spring 后續(xù)實(shí)現(xiàn) AOP 就是基于這個(gè)地方判斷的。
這個(gè)方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 兩個(gè)方法,before 為實(shí)例化前的后處理器應(yīng)用,after 為實(shí)例化后的后處理器應(yīng)用。

第4步

doCreateBean()
創(chuàng)建Bean

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

	// Instantiate the bean.
	//BeanWrapper是對(duì)Bean的包裝,其接口中所定義的功能很簡(jiǎn)單包括設(shè)置獲取被包裝的對(duì)象,獲取被包裝bean的屬性描述器
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	        //單例模式,刪除factoryBean緩存
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	        //使用合適的實(shí)例化策略來(lái)創(chuàng)建Bean:工廠方法、構(gòu)造函數(shù)自動(dòng)注入、簡(jiǎn)單初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	//從包裝類中獲取實(shí)例化的Bean
	final Object bean = instanceWrapper.getWrappedInstance();
	//獲取實(shí)例化對(duì)象的類型
	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 {
			        //調(diào)用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.
	// 解決單例模式的循環(huán)依賴
	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");
		}
		//這里是一個(gè)匿名內(nèi)部類,為了防止循環(huán)引用,盡早持有對(duì)象的引用
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	//Bean對(duì)象的初始化,依賴注入在此觸發(fā)
	//這個(gè)exposedObject在初始化完成之后返回作為依賴注入完成后的Bean
	Object exposedObject = bean;
	try {
		//將Bean實(shí)例對(duì)象封裝,并且Bean定義中配置的屬性值賦值給實(shí)例對(duì)象
		populateBean(beanName, mbd, instanceWrapper);
		//初始化Bean對(duì)象
		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) {
		//獲取指定名稱的已注冊(cè)的單例模式Bean對(duì)象
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			//根據(jù)名稱獲取的已注冊(cè)的Bean和正在實(shí)例化的Bean是同一個(gè)
			if (exposedObject == bean) {
				//當(dāng)前實(shí)例化的Bean初始化完成
				exposedObject = earlySingletonReference;
			}
			//當(dāng)前Bean依賴其他Bean,并且當(dāng)發(fā)生循環(huán)引用時(shí)不允許新創(chuàng)建實(shí)例對(duì)象
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				//獲取當(dāng)前Bean所依賴的其他Bean
				for (String dependentBean : dependentBeans) {
					//對(duì)依賴Bean進(jìn)行類型檢查
					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.
	//注冊(cè)完成依賴注入的Bean
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
	}

代碼很長(zhǎng),不過別慌,我們來(lái)按步驟分析一波

  1. 如果是單例模式,從factoryBeanInstanceCache 緩存中獲取BeanWrapper 實(shí)例對(duì)象并刪除緩存

  2. 調(diào)用 createBeanInstance() 實(shí)例化 bean
    (主要是將 BeanDefinition 轉(zhuǎn)換為 BeanWrapper)

  3. 后置處理

  4. 單例模式的循環(huán)依賴處理

  5. 初始化 bean 實(shí)例對(duì)象
    (屬性填充)

  6. 依賴檢查

  7. 注冊(cè) DisposableBean

doCreateBean() 完成 bean 的創(chuàng)建和初始化工作,內(nèi)容太多,比較復(fù)雜,這里只列出大致流程,接下來(lái)我們將分幾篇文章來(lái)分別闡述相關(guān)內(nèi)容。

感謝各位的閱讀,以上就是“Spring  Ioc中Bean的加載實(shí)現(xiàn)方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Spring  Ioc中Bean的加載實(shí)現(xiàn)方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


當(dāng)前文章:SpringIoc中Bean的加載實(shí)現(xiàn)方法
當(dāng)前路徑:http://weahome.cn/article/ppjcch.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部