1. 程式人生 > >Spring原始碼:bean建立(四)屬性注入

Spring原始碼:bean建立(四)屬性注入

一、populateBean

在建立了bean的例項後,Spring的下一步工作就是為bean注入其依賴的屬性:

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		//傳入的beanWrapper為空,如果屬性不為空就丟擲異常,否則返回null
		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.
				return;
			}
		}

		// 應用後處理器InstantiationAwareBeanPostProcessor,呼叫其postProcessAfterInstantiation方法
		// 在注入屬性前修改bean狀態,如果方法中發揮false的話,可以終止後面程式碼執行,直接返回
		boolean continueWithPropertyPopulation = true;
		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);
		//為bean注入PropertyValues中包含的屬性
		//這種注入方式適用的是配置檔案中通過<property>配置的屬性並且顯示在配置檔案中配置了autowireMode屬性
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// 根據名稱自動注入
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// 根據型別自動注入
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
		//如果存在InstantiationAwareBeanPostProcessor後處理器 || 需要進行依賴檢查
		//一般情況下,Spring會提前註冊幾種存在InstantiationAwareBeanPostProcessor
		if (hasInstAwareBpps || needsDepCheck) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						//應用後處理器InstantiationAwareBeanPostProcessor,呼叫其postProcessPropertyValues方法
						//作用是對需要進行依賴檢查的屬性進行處理
						//Autowired等註解的屬性就是在這裡完成注入的
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}
		//注入配置檔案中<property>配置的屬性
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

處理流程:

  1. 應用InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation方法。該方法可以控制是否繼續進行屬性填充
  2. 獲取配置檔案中配置的property屬性
  3. 應用InstantiationAwareBeanPostProcessor處理器的postProcessPropertyValues方法,完成對注入屬性的驗證、處理。值得注意的是,AutowiredAnnotationBeanPostProcessor會負責注入標註有@Autowired等註解的屬性.
  4. 將配置的<property>屬性注入到bean中

二、配置屬性的注入

對於通過配置檔案中給<bean>配置<property>節點來完成注入的程式碼實現在applyPropertyValues中:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs == null || pvs.isEmpty()) {
			return;
		}
		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;
		if (System.getSecurityManager() != null) {
			if (bw instanceof BeanWrapperImpl) {
				((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
			}
		}
		//BeanDefinition中定義的PropertyValues的型別就是MutablePropertyValues,所以為true
		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			//屬性是否已經轉換過型別了
			if (mpvs.isConverted()) {
				// 如果屬性已經轉換為對應的型別,則直接設定到BeanWrapper中
				try {
					bw.setPropertyValues(mpvs);
					return;
				}
				//catch 
			}
			//獲取配置檔案中配置的原始值
			original = mpvs.getPropertyValueList();
		}
		else {
			original = Arrays.asList(pvs.getPropertyValues());
		}
		//獲取型別轉換器,如果沒有配置的話為null
		TypeConverter converter = getCustomTypeConverter();
		//如果型別轉換器為null,則使用BeanWrapper作為型別轉換器,因為BeanWrapper實現了TypeConverter介面
		if (converter == null) {
			converter = bw;
		}
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// 遍歷屬性,並將配置的值轉換為對應的型別
		List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {
				deepCopy.add(pv);
			}
			else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				//解析原始值,例如RuntimeBeanReference型別,會獲取BeanFactory中其真正的bean;String或TypedStringValue型別會視為一個表示式進行求值等
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				//是否能進行型別轉換 = 可以寫入 && 沒有'.'或者'[' 符號
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
					//將value轉換為對應的型別
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}

				//為了避免每次建立bean的時候都重複轉換型別,Spring會盡可能地將轉換好的值放入對應的BeanDefinition中
				if (resolvedValue == originalValue) {
					//如果原始值並未進行解析
					if (convertible) {
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				}
				else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
					//需要進行解析的情況
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				}
				else {
					//無法被快取
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			mpvs.setConverted();
		}

		// 將解析、轉換好的屬性設定到BeanWrapper中
		//之所以bean需要BeanWrapper包裝一次,也是為了方便給bean填充屬性
		try {
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}

最終是通過BeanWrapper的setPropertyValues來完成屬性的注入,而前面的工作主要是解析配置檔案配置的原始值,因為原始值可能是最終注入的值(String型別),也可能需要被解析後才能被應用,所以Spring花費大量工作來解析原始值。解析完成後,如果有必要還得轉換值的型別,最終將解析、轉換好的值注入到bean中。

	public void setPropertyValues(PropertyValues pvs) throws BeansException {
		setPropertyValues(pvs, false, false);
	}

	public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
			throws BeansException {
		//儲存注入時丟擲的PropertyAccessException
		List<PropertyAccessException> propertyAccessExceptions = null;
		//獲取需要注入的propertyValue列表
		List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
				((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
		for (PropertyValue pv : propertyValues) {
			try {
				// 注入屬性
				setPropertyValue(pv);
			}
			catch (NotWritablePropertyException|NullValueInNestedPathException ex) {
				if (!ignoreUnknown) {
					throw ex;
				}
			} catch (PropertyAccessException ex) {
				if (propertyAccessExceptions == null) {
					propertyAccessExceptions = new LinkedList<PropertyAccessException>();
				}
				propertyAccessExceptions.add(ex);
			}
		}

		// 如果注入時丟擲的PropertyAccessException不為空,Spring會收集起來,在這裡統一丟擲
		if (propertyAccessExceptions != null) {
			PropertyAccessException[] paeArray =
					propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
			throw new PropertyBatchUpdateException(paeArray);
		}
	}

在上面的程式碼中主要是進行統一的異常處理和遍歷屬性列表,真正的屬性注入還需要繼續向下呼叫設定單個屬性的方法setPropertyValue:

	public void setPropertyValue(PropertyValue pv) throws BeansException {
		setPropertyValue(pv.getName(), pv.getValue());
	}
	
	public void setPropertyValue(String propertyName, Object value) throws BeansException {
		AbstractNestablePropertyAccessor nestedPa;
		try {
			//將屬性訪問的工作交給AbstractNestablePropertyAccessor完成
			//當配置的屬性名propertyName中包含'.'或者'['這樣字元時,代表需要設定巢狀屬性
			//如果存在巢狀屬性,Spring會遞歸向下獲取最終設定的屬性,比如:a.b.c,Spring會遞迴呼叫獲取到b,c是需要設定的屬性
			//如果沒有巢狀屬性的話。會返回BeanWrapper自身
			nestedPa = getPropertyAccessorForPropertyPath(propertyName);
		}
		catch (NotReadablePropertyException ex) {
			throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
					"Nested property in path '" + propertyName + "' does not exist", ex);
		}
		PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
		//設定屬性
		nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
	}

上面主要是解析propertyName,處理巢狀的屬性,確定最終需要設定的屬性

	protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
		//如果propertyName中存在'['的情況,即存在陣列下標
		if (tokens.keys != null) {
			processKeyedProperty(tokens, pv);
		}
		else {
			//非陣列、容器型別的屬性設定
			processLocalProperty(tokens, pv);
		}
	}

屬性設定分為了陣列型別設定和非陣列型別設定,我們分析更為普遍的非陣列型別:

	private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
		//屬性設定交由PropertyHandler完成
        //Spring會使用反射獲取屬性的getter和setter方法
		PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
		//如果不存在屬性或者屬性不是可寫的
		if (ph == null || !ph.isWritable()) {
			//如果屬性是Optional型別,則直接返回
			if (pv.isOptional()) {
				//日誌,略
				return;
			} else {
				//其他情況會丟擲異常
				throw createNotWritablePropertyException(tokens.canonicalName);
			}
		}

		Object oldValue = null;
		try {
			//獲取屬性值
			Object originalValue = pv.getValue();
			Object valueToApply = originalValue;
			//需要轉換值的型別
			if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
				//如果已經完成了型別轉換,直接使用就可以了
				if (pv.isConverted()) {
					valueToApply = pv.getConvertedValue();
				}
				else {
					//如果需要讀取舊值(預設為false) && 值是可讀的
					if (isExtractOldValueForEditor() && ph.isReadable()) {
						try {
							oldValue = ph.getValue();
						}
						catch (Exception ex) {
							//無法讀取舊值
						}
					}
					//型別裝換
					valueToApply = convertForProperty(
							tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
				}
				pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
			}
			//使用PropertyHandler完成屬性的注入
			ph.setValue(this.wrappedObject, valueToApply);
		}
		//catch略
	}

下面就是注入屬性的程式碼:

		public void setValue(final Object object, Object valueToApply) throws Exception {
			//獲取解析好的setter方法
			final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
					((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
					this.pd.getWriteMethod());
			//設定Method的訪問許可權
			if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							writeMethod.setAccessible(true);
							return null;
						}
					});
				}
				else {
					writeMethod.setAccessible(true);
				}
			}
			//呼叫setterMethod的invoke方法,通過反射,完成屬性的注入
			final Object value = valueToApply;
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
							writeMethod.invoke(object, value);
							return null;
						}
					}, acc);
				}
				catch (PrivilegedActionException ex) {
					throw ex.getException();
				}
			}
			else {
				writeMethod.invoke(getWrappedInstance(), value);
			}
		}
	}

至此,配置檔案中的peoperty已經注入到了bean中

三、Autowired註解的屬性注入

在屬性填充populateBean程式碼中,除了呼叫applyPropertyValues注入配置檔案中配置的屬性,在它前面有一段程式碼會應用 InstantiationAwareBeanPostProcessor後處理器的postProcessPropertyValues方法:

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						//應用InstantiationAwareBeanPostProcessor後處理器
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						//返回值為null時會屬性的填充,直接返回
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}
		//配置檔案的屬性注入
		applyPropertyValues(beanName, mbd, bw, pvs);

在InstantiationAwareBeanPostProcessor的子類中,就包含了註解屬性注入的實現方法,InstantiationAwareBeanPostProcessor的子類有:

重點需要關注的有以下幾個實現類:

  • RequiredAnnotationBeanPostProcessor:檢查屬性的setter方法上是否標註有@Required註解,如果帶有此註解,但是未配置屬性(配置檔案中的<property>元素),那麼就會丟擲異常
  • AutowiredAnnotationBeanPostProcessor:遍歷bean的Field屬性,尋找標註有@Autowired和@Value註解的欄位,並完成屬性注入(如果能載入到javax.inject.Inject註解的話,也會掃描該註解)
  • CommonAnnotationBeanPostProcessor:遍歷bean的欄位,尋找通用的依賴(javax中規定的)註解,完成屬性注入。通用註解包括有:javax.annotation.Resource,javax.xml.ws.WebServiceRef,javax.ejb.EJB

重點講解AutowiredAnnotationBeanPostProcessor的實現:

	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
		//遍歷獲取帶有自動注入註解的欄位和方法,並且將欄位資訊、註解資訊
		//註解包括:@Value、@Autowired、@Inject(javax.inject.Inject,如果能載入到這個類的話)
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//屬性注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}
	
	

上面程式碼的步驟為:

  1. 尋找帶有@Value、@Autowired、@Inject(javax.inject.Inject,如果能載入到這個類的話)註解的欄位或方法,並且將欄位或方法、bean名、bean型別封裝起來
  2. 完成屬性注入

1、尋找註解標記的屬性

尋找註解過的屬性在findAutowiringMetadata中實現:

	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
		// 先嚐試從快取中查詢,cacheKey為beanName或類名
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		//如果快取未空 或者 需要解析的類與緩衝的類不同,則需要重新整理快取
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				//雙重判斷,避免多執行緒問題,與單例模式實現類似
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					try {
						//解析後放入快取
						metadata = buildAutowiringMetadata(clazz);
						this.injectionMetadataCache.put(cacheKey, metadata);
					}
					//catch略
				}
			}
		}
		return metadata;
	}

因為對類的解析需要大量用到反射,所以為了盡力提高效能,Spring會將解析好的欄位、方法資訊儲存到快取中,上面的程式碼也在主要是對快取進行管理,具體的解析工作在buildAutowiringMetadata方法中完成:

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		//存放解析好的屬性資訊
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
		Class<?> targetClass = clazz;

		//Spring會一直遞歸向上遍歷bean的父類
		do {
			//存放當前解析的類中帶有註解的屬性
			final LinkedList<InjectionMetadata.InjectedElement> currElements =
					new LinkedList<InjectionMetadata.InjectedElement>();

			//doWithLocalFields方法中,其實就是獲取class的所有欄位,對每個欄位呼叫FieldCallback方法
			//
			ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
					AnnotationAttributes ann = findAutowiredAnnotation(field);
					if (ann != null) {
						if (Modifier.isStatic(field.getModifiers())) {
							return;
						}
						//如果註解中存在required屬性,獲取屬性的值,並儲存起來
						//如果不存在required屬性則預設為true
						boolean required = determineRequiredStatus(ann);
						//使用AutowiredFieldElement型別,將欄位資訊封裝起來
						currElements.add(new AutowiredFieldElement(field, required));
					}
				}
			});
			//與Field邏輯相同,都是遍歷所有宣告的方法,判斷是否帶有特定的註解
			//如果存在註解標註的方法,並使用AutowiredMethodElement封裝起來
			ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
				@Override
				public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
					if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
						return;
					}
					AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
					if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
						if (Modifier.isStatic(method.getModifiers())) {
							//log...
							return;
						}
						if (method.getParameterTypes().length == 0) {
							//log...
						}
						boolean required = determineRequiredStatus(ann);
						//與field不同的一點就是,AutowiredMethodElement會獲取屬性描述符,一起封裝
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new AutowiredMethodElement(method, required, pd));
					}
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		//Spring會一直遞歸向上遍歷bean的父類
		while (targetClass != null && targetClass != Object.class);
		//將封裝有注入屬性的列表一起封裝到InjectionMetadata中
		return new InjectionMetadata(clazz, elements);
	}

上面程式碼中,Spring先從當前類開始解析其欄位和方法,並且會一直遞歸向上解析父類,把解析到的欄位或方法資訊封裝到AutowiredFieldElement或AutowiredMethodElement中。

2、屬性注入

回顧下先前的程式碼:

顯示查詢帶有特定註解的屬性,已經完成了,下一步就是屬性注入,inject:

	public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> elementsToIterate =
				(this.checkedElements != null ? this.checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				element.inject(target, beanName, pvs);
			}
		}
	}

程式碼較短,主要內容就是遍歷先前解析好的AutowiredFieldElement或AutowiredMethodElement,呼叫其inject方法:

		//AutowiredFieldElement
		protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
			//AutowiredFieldElement中儲存的是Field物件,如果是AutowiredMethodElement則會儲存Method物件
			Field field = (Field) this.member;
			//最終需要注入的值
			Object value;
			//如果已經被快取過,就可以從快取中獲取
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				//使用DependencyDescriptor封裝Field
				//其屬性包括:field:Field物件,declaringClass:Field所在類,fieldName:欄位名
				//required:是否允許為空,eager:是否懶載入(註解標註的欄位都為false)
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//通過BeanFactory根據DependencyDescriptor資訊解決依賴
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					//將解析結果放入快取
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							//在BeanFactory中註冊依賴關係
							registerDependentBeans(beanName, autowiredBeanNames);
							//如果與屬性型別相同的注入bean只有一個,那麼就可以設定到快取中
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName)) {
									if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
										this.cachedFieldValue = new ShortcutDependencyDescriptor(
												desc, autowiredBeanName, field.getType());
									}
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			//通過Field物件的反射,將值設定到bean中
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

上面程式碼步驟為:

  1. 先嚐試從快取中獲取屬性值
  2. 如果沒有被快取,則通過beanFactory.resolveDependency方法,從BeanFactory中獲取屬性值
  3. 如果屬性值滿足條件(符合注入條件的bean只有一個、BeanFactory包含該bean、與屬性型別相同),就快取起來
  4. 通過反射,將屬性值設定到bean中

beanFactory.resolveDependenc會將BeanFactory中,所有與傳入引數的型別匹配的bean找出來,有autowiredBeanName儲存這些匹配的beanName