Spring源碼學習(三)炒雞丁與populateBean沒區別

  • 2019 年 10 月 4 日
  • 筆記

邏輯說明

populateBean的流程

炒雞丁的流程

1.執行InstantiationAwareBeanPostProcessor 的postProcessAfterInstantiation (在設置屬性前去修改Bean的狀態,也可以控制是否繼續填充Bean)

作為一個已婚男人炒菜之前,請示老婆,這很重要。 我:「我炒宮爆雞丁了,有特殊要求嗎?」 老婆大人:「沒有要求,炒吧」。

2.注入屬性到PropertyValues中(autowireByName/autowireByType)

初步準備食材 準備雞肉,郫縣豆瓣醬,花生米,黃瓜

3.執行InstantiationAwareBeanPostProcessor的postProcessPropertyValues, 對解析完但未設置的屬性再進行處理

切菜 雞肉切丁,黃瓜切小塊。

4.對dependency-check屬性的支援,默認是不校驗

5.將PropertyValues中的屬性值設置到BeanWrapper中

下鍋,炒熟出鍋

autowirebyType的大致邏輯

看了源碼總結如下:

  1. 不處理簡單屬性,即不處理:Enum,CharSequence,Number,Date,URI,Locale等。(具體可以查看org.springframework.beans.BeanUtils#isSimpleProperty這個方法。)
  2. 不對Object類型的屬性進行自動注入, 沒有意義,技術無法實現
  3. 解析依賴resolveDependency並設置到pvs中
  4. registerDependentBean 註冊當前依賴。

autowiredByType的源碼注釋

/**  	 * Abstract method defining "autowire by type" (bean properties by type) behavior.  	 * 抽象方法 定義 按類型注入  	 * <p>This is like PicoContainer default, in which there must be exactly one bean  	 * of the property type in the bean factory. This makes bean factories simple to  	 * configure for small namespaces, but doesn't work as well as standard Spring  	 * behavior for bigger applications.  	 * 類似PicoContainer(非常輕量級的Ioc容器),beanFactory中一個屬性類型必須有一個確切對應的bean  	 * bean工廠很容易配置小的命名空間.  	 * @param beanName the name of the bean to autowire by type  需要按類型注入的BeanName  	 * @param mbd the merged bean definition to update through autowiring   合併後的BeanDefinition  	 * @param bw the BeanWrapper from which we can obtain information about the bean  BeanWrapper對象  	 * @param pvs the PropertyValues to register wired objects with 註冊屬性的屬性值  	 */  	protected void autowireByType(  			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  		//獲取類型轉換器  		TypeConverter converter = getCustomTypeConverter();  		if (converter == null) {  			converter = bw;  		}  		//獲取需要 注入的 非簡單類型  		/**  		 * 簡單類型,詳見  		 * @see org.springframework.beans.BeanUtils#isSimpleProperty  		 */  		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);  		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);    		for (String propertyName : propertyNames) {  			try {  				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);  				// Don't try autowiring by type for type Object: never makes sense,  				// even if it technically is a unsatisfied, non-simple property.  				// 不對Object類型的屬性進行自動注入, 沒有意義,技術無法實現  				if (Object.class != pd.getPropertyType()) {  					//獲得屬性寫的方法  					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);  					// Do not allow eager init for type matching in case of a prioritized post-processor.  					// 假如實現了prioritized post-processor ,在進行類型匹配時,是不允許,eager初始化(熱載入)的  					boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());  					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);  					//解析依賴  					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);  					if (autowiredArgument != null) {  						pvs.add(propertyName, autowiredArgument);  					}  					for (String autowiredBeanName : autowiredBeanNames) {  						//註冊依賴  						registerDependentBean(autowiredBeanName, beanName);  						if (logger.isTraceEnabled()) {  							logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +  									propertyName + "' to bean named '" + autowiredBeanName + "'");  						}  					}  					autowiredBeanNames.clear();  				}  			}  			catch (BeansException ex) {  				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);  			}  		}  	}

下回寫resolveDependency的邏輯。

一圖勝千言

源碼注釋

	/**  	 * Populate the bean instance in the given BeanWrapper with the property values  	 * from the bean definition.  	 * 填充bean的屬性  	 * @param beanName the name of the bean   bean的名稱  	 * @param mbd the bean definition for the bean 合併後的Bean的定義  	 * @param bw the BeanWrapper with bean instance   beanWrapper的對象  	 */  	@SuppressWarnings("deprecation")  // for postProcessPropertyValues  	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {  		if (bw == null) {  			if (mbd.hasPropertyValues()) {  				throw new BeanCreationException(  						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  			}  			else {  				// Skip property population phase for null instance.  				// 跳過沒有屬性,null實例  				return;  			}  		}    		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the  		// state of the bean before properties are set. This can be used, for example,  		// to support styles of field injection.  		//給任何InstantiationWareBeanPostProcessors在設置屬性之前修改bean的狀態的機會。  		// 例如,這可用於支援屬性注入  		boolean continueWithPropertyPopulation = true;  		//InstantiationWareBeanPostProcessors  可以控制是否繼續填充bean  		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  			for (BeanPostProcessor bp : getBeanPostProcessors()) {  				if (bp instanceof InstantiationAwareBeanPostProcessor) {  					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  						continueWithPropertyPopulation = false;  						break;  					}  				}  			}  		}    		if (!continueWithPropertyPopulation) {  			return;  		}    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);    		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {  			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  			// Add property values based on autowire by name if applicable.  			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {  				//根據名稱自動注入  				autowireByName(beanName, mbd, bw, newPvs);  			}  			// Add property values based on autowire by type if applicable.  			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {  				//根據類型自動注入  				autowireByType(beanName, mbd, bw, newPvs);  			}  			pvs = newPvs;  		}    		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);    		PropertyDescriptor[] filteredPds = null;  		if (hasInstAwareBpps) {  			//有InstantiationAwareBeanPostProcessors 對象  			if (pvs == null) {  				pvs = mbd.getPropertyValues();  			}  			for (BeanPostProcessor bp : getBeanPostProcessors()) {  				if (bp instanceof InstantiationAwareBeanPostProcessor) {  					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);  					if (pvsToUse == null) {  						if (filteredPds == null) {  							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  						}  						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  						if (pvsToUse == null) {  							return;  						}  					}  					pvs = pvsToUse;  				}  			}  		}  		if (needsDepCheck) {  			if (filteredPds == null) {  				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  			}  			//檢查依賴Dependency-check  			checkDependencies(beanName, mbd, filteredPds, pvs);  		}    		if (pvs != null) {  			//將屬性值設置到Bean中  			applyPropertyValues(beanName, mbd, bw, pvs);  		}  	}

Tags: