spring原始碼深度解析— IOC 之 屬性填充

chen_hao發表於2019-07-09

doCreateBean() 主要用於完成 bean 的建立和初始化工作,我們可以將其分為四個過程:

  • createBeanInstance() 例項化 bean
  • populateBean() 屬性填充
  • 迴圈依賴的處理
  • initializeBean() 初始化 bean

第一個過程例項化 bean在前面一篇部落格中已經分析完了,這篇部落格開始分析 屬性填充,也就是 populateBean()

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {  
    PropertyValues pvs = mbd.getPropertyValues();  

    if (bw == null) {  
        if (!pvs.isEmpty()) {  
            throw new BeanCreationException(  
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  
        }  
        else {  
            // Skip property population phase for null instance.  
            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.  
    boolean continueWithPropertyPopulation = true;  

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
        for (BeanPostProcessor bp : getBeanPostProcessors()) {  
            if (bp instanceof InstantiationAwareBeanPostProcessor) {  
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
                //返回值為是否繼續填充bean  
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
                    continueWithPropertyPopulation = false;  
                    break;  
                }  
            }  
        }  
    }  
    //如果後處理器發出停止填充命令則終止後續的執行  
    if (!continueWithPropertyPopulation) {  
        return;  
    }  

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  

        // Add property values based on autowire by name if applicable.  
        //根據名稱自動注入  
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
            autowireByName(beanName, mbd, bw, newPvs);  
        }  

        // Add property values based on autowire by type if applicable.  
        //根據型別自動注入  
        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);  

    if (hasInstAwareBpps || needsDepCheck) {  
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  
        if (hasInstAwareBpps) {  
            for (BeanPostProcessor bp : getBeanPostProcessors()) {  
                if (bp instanceof InstantiationAwareBeanPostProcessor) {  
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
                    //對所有需要依賴檢查的屬性進行後處理  
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  
                    if (pvs == null) {  
                        return;  
                    }  
                }  
            }  
        }  
        if (needsDepCheck) {  
            //依賴檢查,對應depends-on屬性,3.0已經棄用此屬性  
            checkDependencies(beanName, mbd, filteredPds, pvs);  
        }  
    }  
    //將屬性應用到bean中  
    //將所有ProtertyValues中的屬性填充至BeanWrapper中。  
    applyPropertyValues(beanName, mbd, bw, pvs);  
} 

我們詳細分析下populateBean的流程:
(1)首先進行屬性是否為空的判斷
(2)通過呼叫InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)方法來控制程式是否繼續進行屬性填充
(3)根據注入型別(byName/byType)提取依賴的bean,並統一存入PropertyValues中
(4)應用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName)方法,對屬性獲取完畢填充前的再次處理,典型的應用是RequiredAnnotationBeanPostProcesser類中對屬性的驗證
(5)將所有的PropertyValues中的屬性填充至BeanWrapper中
上面步驟中有幾個地方是我們比較感興趣的,它們分別是依賴注入(autowireByName/autowireByType)以及屬性填充,接下來進一步分析這幾個功能的實現細節

自動注入

Spring 會根據注入型別( byName / byType )的不同,呼叫不同的方法(autowireByName() / autowireByType())來注入屬性值。

autowireByName()

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    // 獲取 Bean 物件中非簡單屬性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        // 如果容器中包含指定名稱的 bean,則將該 bean 注入到 bean中
        if (containsBean(propertyName)) {
            // 遞迴初始化相關 bean
            Object bean = getBean(propertyName);
            // 為指定名稱的屬性賦予屬性值  
            pvs.add(propertyName, bean);
            // 屬性依賴注入
            registerDependentBean(propertyName, beanName);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                        "' by name: no matching bean found");
            }
        }
    }
}

該方法邏輯很簡單,獲取該 bean 的非簡單屬性,什麼叫做非簡單屬性呢?就是型別為物件型別的屬性,但是這裡並不是將所有的物件型別都都會找到,比如 8 個原始型別,String 型別 ,Number型別、Date型別、URL型別、URI型別等都會被忽略,如下:

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    Set<String> result = new TreeSet<>();
    PropertyValues pvs = mbd.getPropertyValues();
    PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
                !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
            result.add(pd.getName());
        }
    }
    return StringUtils.toStringArray(result);
}

這裡獲取的就是需要依賴注入的屬性。

autowireByName()函式的功能就是根據傳入的引數中的pvs中找出已經載入的bean,並遞迴例項化,然後加入到pvs中

autowireByType

autowireByType與autowireByName對於我們理解與使用來說複雜程度相似,但是實現功能的複雜度卻不一樣,我們看下方法程式碼:

protected void autowireByType(  
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  

    TypeConverter converter = getCustomTypeConverter();  
    if (converter == null) {  
        converter = bw;  
    }  

    Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);  
    //尋找bw中需要依賴注入的屬性  
    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.  
            if (!Object.class.equals(pd.getPropertyType())) {  
                //探測指定屬性的set方法  
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);  
                // Do not allow eager init for type matching in case of a prioritized post-processor.  
                boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());  
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);  
                //解析指定beanName的屬性所匹配的值,並把解析到的屬性名稱儲存在autowiredBeanNames中,  
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);  
                if (autowiredArgument != null) {  
                    pvs.add(propertyName, autowiredArgument);  
                }  
                for (String autowiredBeanName : autowiredBeanNames) {  
                    //註冊依賴  
                    registerDependentBean(autowiredBeanName, beanName);  
                    if (logger.isDebugEnabled()) {  
                        logger.debug("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);  
        }  
    }  
}

根據名稱第一步與根據屬性第一步都是尋找bw中需要依賴注入的屬性,然後遍歷這些屬性並尋找型別匹配的bean,其中最複雜就是尋找型別匹配的bean。spring中提供了對集合的型別注入支援,如使用如下註解方式:

@Autowired
private List<Test> tests;

這種方式spring會把所有與Test匹配的型別找出來並注入到tests屬性中,正是由於這一因素,所以在autowireByType函式,新建了區域性遍歷autowireBeanNames,用於儲存所有依賴的bean,如果只是對非集合類的屬性注入來說,此屬性並無用處。
對於尋找型別匹配的邏輯實現是封裝在了resolveDependency函式中,其實現如下:

 

public Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());  
    if (descriptor.getDependencyType().equals(ObjectFactory.class)) {  
        //ObjectFactory類注入的特殊處理  
        return new DependencyObjectFactory(descriptor, beanName);  
    }  
    else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) {  
        //javaxInjectProviderClass類注入的特殊處理  
        return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);  
    }  
    else {  
        //通用處理邏輯  
        return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);  
    }  
}  

protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,  
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {  
    /* 
     * 用於支援Spring中新增的註解@Value 
     */  
    Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);  
    if (value != null) {  
        if (value instanceof String) {  
            String strVal = resolveEmbeddedValue((String) value);  
            BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);  
            value = evaluateBeanDefinitionString(strVal, bd);  
        }  
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());  
        return (descriptor.getField() != null ?  
                converter.convertIfNecessary(value, type, descriptor.getField()) :  
                converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));  
    }  
    //如果解析器沒有成功解析,則需要考慮各種情況  
    //屬性是陣列型別  
    if (type.isArray()) {  
        Class<?> componentType = type.getComponentType();  
        //根據屬性型別找到beanFactory中所有型別的匹配bean,  
        //返回值的構成為:key=匹配的beanName,value=beanName對應的例項化後的bean(通過getBean(beanName)返回)  
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);  
        if (matchingBeans.isEmpty()) {  
            //如果autowire的require屬性為true而找到的匹配項卻為空則只能丟擲異常  
            if (descriptor.isRequired()) {  
                raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);  
            }  
            return null;  
        }  
        if (autowiredBeanNames != null) {  
            autowiredBeanNames.addAll(matchingBeans.keySet());  
        }  
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());  
        //通過轉換器將bean的值轉換為對應的type型別  
        return converter.convertIfNecessary(matchingBeans.values(), type);  
    }  
    //屬性是Collection型別  
    else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {  
        Class<?> elementType = descriptor.getCollectionType();  
        if (elementType == null) {  
            if (descriptor.isRequired()) {  
                throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");  
            }  
            return null;  
        }  
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);  
        if (matchingBeans.isEmpty()) {  
            if (descriptor.isRequired()) {  
                raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);  
            }  
            return null;  
        }  
        if (autowiredBeanNames != null) {  
            autowiredBeanNames.addAll(matchingBeans.keySet());  
        }  
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());  
        return converter.convertIfNecessary(matchingBeans.values(), type);  
    }  
    //屬性是Map型別  
    else if (Map.class.isAssignableFrom(type) && type.isInterface()) {  
        Class<?> keyType = descriptor.getMapKeyType();  
        if (keyType == null || !String.class.isAssignableFrom(keyType)) {  
            if (descriptor.isRequired()) {  
                throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +  
                        "] must be assignable to [java.lang.String]");  
            }  
            return null;  
        }  
        Class<?> valueType = descriptor.getMapValueType();  
        if (valueType == null) {  
            if (descriptor.isRequired()) {  
                throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");  
            }  
            return null;  
        }  
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);  
        if (matchingBeans.isEmpty()) {  
            if (descriptor.isRequired()) {  
                raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);  
            }  
            return null;  
        }  
        if (autowiredBeanNames != null) {  
            autowiredBeanNames.addAll(matchingBeans.keySet());  
        }  
        return matchingBeans;  
    }  
    else {  
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);  
        if (matchingBeans.isEmpty()) {  
            if (descriptor.isRequired()) {  
                raiseNoSuchBeanDefinitionException(type, "", descriptor);  
            }  
            return null;  
        }  
        if (matchingBeans.size() > 1) {  
            String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);  
            if (primaryBeanName == null) {  
                throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());  
            }  
            if (autowiredBeanNames != null) {  
                autowiredBeanNames.add(primaryBeanName);  
            }  
            return matchingBeans.get(primaryBeanName);  
        }  
        // We have exactly one match.  
        Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();  
        if (autowiredBeanNames != null) {  
            autowiredBeanNames.add(entry.getKey());  
        }  
        //已經確定只有一個匹配項  
        return entry.getValue();  
    }  
}

applyPropertyValues

程式執行到這裡,已經完成了對所有注入屬性的獲取,但是獲取的屬性是以PropertyValues形式存在的,還並沒有應用到已經例項化的bean中,這一工作是在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());  
        }  
    }  

    if (pvs instanceof MutablePropertyValues) {  
        mpvs = (MutablePropertyValues) pvs;  
        //如果mpvs中的值已經被轉換為對應的型別那麼可以直接設定到beanwapper中  
        if (mpvs.isConverted()) {  
            // Shortcut: use the pre-converted values as-is.  
            try {  
                bw.setPropertyValues(mpvs);  
                return;  
            }  
            catch (BeansException ex) {  
                throw new BeanCreationException(  
                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
            }  
        }  
        original = mpvs.getPropertyValueList();  
    }  
    else {  
        //如果pvs並不是使用MutablePropertyValues封裝的型別,那麼直接使用原始的屬性獲取方法  
        original = Arrays.asList(pvs.getPropertyValues());  
    }  

    TypeConverter converter = getCustomTypeConverter();  
    if (converter == null) {  
        converter = bw;  
    }  
    //獲取對應的解析器  
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);  

    // Create a deep copy, resolving any references for values.  
    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();  
            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);  
            }  
            // Possibly store converted value in merged bean definition,  
            // in order to avoid re-conversion for every created bean instance.  
            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();  
    }  

    // Set our (possibly massaged) deep copy.  
    try {  
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));  
    }  
    catch (BeansException ex) {  
        throw new BeanCreationException(  
                mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
    }  
}

我們來看看具體的屬性賦值過程

public class MyTestBean {
    private String name ;

    public MyTestBean(String name) {
        this.name = name;
    }

    public MyTestBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

<bean id="myTestBean"  class="chenhao.spring01.MyTestBean">
        <property name="name" value="chenhao"></property>
</bean>

如上 bw.setPropertyValues 最終都會走到如下方法

@Override
public void setValue(final @Nullable Object value) throws Exception {
    //獲取writeMethod,也就是我們MyTestBean的setName方法
    final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
            ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
            this.pd.getWriteMethod());
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(writeMethod);
            return null;
        });
        try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
                    writeMethod.invoke(getWrappedInstance(), value), acc);
        }
        catch (PrivilegedActionException ex) {
            throw ex.getException();
        }
    }
    else {
        ReflectionUtils.makeAccessible(writeMethod);
        //通過反射呼叫方法進行賦值
        writeMethod.invoke(getWrappedInstance(), value);
    }
}

Debug如下

就是利用反射進行呼叫物件的set方法賦值

至此,doCreateBean() 第二個過程:屬性填充 已經分析完成了,下篇分析第三個過程:迴圈依賴的處理,其實迴圈依賴並不僅僅只是在 doCreateBean() 中處理,其實在整個載入 bean 的過程中都有涉及,所以下篇內容並不僅僅只侷限於 doCreateBean()

 

相關文章