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); } }
處理流程:
- 應用InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation方法。該方法可以控制是否繼續進行屬性填充
- 獲取配置檔案中配置的property屬性
- 應用InstantiationAwareBeanPostProcessor處理器的postProcessPropertyValues方法,完成對注入屬性的驗證、處理。值得注意的是,AutowiredAnnotationBeanPostProcessor會負責注入標註有@Autowired等註解的屬性.
- 將配置的<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;
}
上面程式碼的步驟為:
- 尋找帶有@Value、@Autowired、@Inject(javax.inject.Inject,如果能載入到這個類的話)註解的欄位或方法,並且將欄位或方法、bean名、bean型別封裝起來
- 完成屬性注入
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);
}
}
}
上面程式碼步驟為:
- 先嚐試從快取中獲取屬性值
- 如果沒有被快取,則通過beanFactory.resolveDependency方法,從BeanFactory中獲取屬性值
- 如果屬性值滿足條件(符合注入條件的bean只有一個、BeanFactory包含該bean、與屬性型別相同),就快取起來
- 通過反射,將屬性值設定到bean中
beanFactory.resolveDependenc會將BeanFactory中,所有與傳入引數的型別匹配的bean找出來,有autowiredBeanName儲存這些匹配的beanName