本系列所有基於 Spring 5.2.2.BUILD-SNAPSHOT
版本。由於 Spring 整個體系太過於龐大,因此只會進行關鍵部分的源碼解析。html
本篇文章主要介紹 Spring IoC 容器中 bean
的屬性賦值階段。java
咱們在Spring IoC bean 的建立一文中分析建立 bean
實例的主要流程,此時建立出來的 bean
仍是個屬性未賦值的實例,在建立完以後會進入 populateBean()
方法,即進入屬性賦值階段。咱們簡單回顧一下,上次分析過的 doCreateBean()
方法:git
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 實例化 bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // 若是bean的做用域是singleton,則須要移除未完成的FactoryBean實例的緩存 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 經過構造函數反射建立bean的實例,可是屬性並未賦值,見下文詳解 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 獲取bean的實例 final Object bean = instanceWrapper.getWrappedInstance(); // 獲取bean的類型 Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // BeanDefinition 合併後的回調,見下文詳解 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } // 省略異常處理... mbd.postProcessed = true; } } // bean的做用域是單例 && 容許循環引用 && 當前bean正在建立中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); // 若是容許bean提早曝光 if (earlySingletonExposure) { // 將beanName和ObjectFactory造成的key-value對放入singletonFactories緩存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { // 給 bean 的屬性賦值 populateBean(beanName, mbd, instanceWrapper); // 初始化 bean exposedObject = initializeBean(beanName, exposedObject, mbd); } // 省略部分代碼 }
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 { return; } } // 給InstantiationAwareBeanPostProcessors最後一次機會在屬性設置前來改變bean // 例如:能夠用來支持屬性注入的類型 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { // 這裏會調用bean實例化後的生命週期回調,返回false會跳過下面的屬性賦值階段 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // 獲取PropertyValues PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 獲取依賴注入類型 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); // 若是依賴注入類型是 byName 或者 byType if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { // 賦值pvs到可修改的MutablePropertyValues MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 根據名稱自動注入,見下文詳解 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 根據類型自動注入,見下文詳解 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 是否有註冊InstantiationAwareBeanPostProcessors的實現類 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // 遍歷並找到InstantiationAwareBeanPostProcessor的實現類,調用處理屬性值的後置處理方法 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); // 若是屬性值的後置處理方法返回null,直接返回,不會進行底下的屬性值應用階段 if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { // 屬性填充,見下文詳解 applyPropertyValues(beanName, mbd, bw, pvs); } }
上面方法首先會調用 bean
的實例化後生命週期回調方法,若是返回 false
會跳過下面的屬性賦值階段。關於 InstantiationAwareBeanPostProcessors
接口在Spring IoC bean 的建立一文中介紹過,這裏再也不贅述。接着判斷是不是按 名稱 或者 類型 自動注入屬性並填入 newPvs
中,接着調用 bean
屬性填充前的生命週期回調。屬性填充前生命週期回調方法有兩個 postProcessProperties()
和 postProcessPropertyValues()
,第一個是 Spring 5.1 新加的,後面的是老的,已經被標記爲過期;首先會調用 postProcessProperties()
若是返回空調用 postProcessPropertyValues()
,不然直接使用返回的 PropertyValues
;postProcessPropertyValues()
若是返回空會直接跳過屬性填充階段,不爲空直接使用返回的 PropertyValues
。github
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // 尋找bw中須要依賴注入的屬性名稱 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); // 遍歷須要注入的bean for (String propertyName : propertyNames) { if (containsBean(propertyName)) { // 調用getBean()方法獲取bean Object bean = getBean(propertyName); // 將須要注入bean的實例加入到pvs pvs.add(propertyName, bean); // 註冊依賴關係 registerDependentBean(propertyName, beanName); } } }
上面的方法很簡單,就是尋找 bean
的非簡單類型而且不存在於 mbd.getPropertyValues()
中的屬性,而後遍歷調用 getBean()
方法去獲取實例,完成注入。spring
非簡單類型就是指除去8個原始類型、String類型、Number類型、Date類型、URL類型、URI類型的其它類型。緩存
registerDependentBean()
方法在Spring IoC bean 的加載一文中有分析過,這裏再也不贅述。app
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 獲取bean中非簡單屬性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); // 根據類型注入永遠不要注入Object類型,你細細地品一下 if (Object.class != pd.getPropertyType()) { // 獲取屬性的可寫方法,通常是set方法 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 依賴解決,最後返回符合條件須要注入的bean實例 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { // 須要注入的bean實例不爲空,加入到pvc pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { // 註冊依賴關係 registerDependentBean(autowiredBeanName, beanName); } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }
上面方法中的 resolveDependency()
方法在Spring IoC bean 的建立一文中介紹過,這裏再也不贅述。函數
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // 屬性爲空,直接返回 if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // 快捷方式,若是屬性已經轉換過,直接填充進BeanWrapper if (mpvs.isConverted()) { try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } // 屬性沒有轉換過,獲取屬性列表 original = mpvs.getPropertyValueList(); } else { // 獲取屬性列表 original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 獲取對應的解析器 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 建立深拷貝,解決引用的問題 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; // 遍歷屬性,將屬性轉換爲對應的類型 for (PropertyValue pv : original) { // 若是pv類型轉換過,直接添加進deepCopy if (pv.isConverted()) { deepCopy.add(pv); } else { // 進行轉換 // 拿到pv原始屬性名和屬性值 String propertyName = pv.getName(); Object originalValue = pv.getValue(); if (originalValue == AutowiredPropertyMarker.INSTANCE) { Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); if (writeMethod == null) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); } // 進行類型轉換 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { // 若是可轉換,則轉換指定目標屬性的給定值 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // 在合併的BeanDefinition中存儲轉換後的值,以免爲每一個建立的bean實例從新轉換 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(); } try { // 填充bean屬性值 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
上面代碼中的 bw.setPropertyValues()
方法最終會調用 BeanWrapperImpl#setVlaue()
方法,以下:post
public void setValue(final @Nullable Object value) throws Exception { // 這裏通常就是setter方法 final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor)this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod()); // 利用反射調用setter方法給屬性賦值 ReflectionUtils.makeAccessible(writeMethod); writeMethod.invoke(getWrappedInstance(), value); }
下圖是我 debug 時的截圖,能夠看到基本上就是在調用屬性的 setter
方法:this
注意:沒有
setter
方法時會拋出異常。
本篇文章主要分析了 Spring IoC 的屬性賦值階段的流程,Spring 在此階段也提供了2個擴展點;分別是 bean
的實例化後和屬性賦值前,即 InstantiationAwareBeanPostProcessor
接口的 postProcessAfterInstantiation()
方法和 postProcessProperties()
方法。須要注意的是在 XML 中配置的 autowire
屬性,無論是 byName
仍是 byType
都須要 setter
方法,可是咱們平時在使用 @Autowire
註解時並不須要 settter
方法,緣由會在分析 @Autowire
註解時講述。
最後,我模仿 Spring 寫了一個精簡版,代碼會持續更新。地址:https://github.com/leisurexi/tiny-spring。