专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  面试官:为什么在系统中不推荐双写? ·  3 天前  
芋道源码  ·  Redis+Caffeine 太强了! ·  5 天前  
芋道源码  ·  在公司整了这套系统架构,同事直呼666! ·  1 周前  
51好读  ›  专栏  ›  ImportNew

Spring 源码分析 : 非懒加载的单例 Bean 初始化过程 ( 下 ) ( 1 )

ImportNew  · 公众号  · Java  · 2017-04-24 14:30

正文

(点击上方公众号,可快速关注)


来源:五月的仓颉,

www.cnblogs.com/xrq730/p/6363055.html

如有好文章投稿,请点击 → 这里了解详情


doCreateBean方法


上文《 Spring源码分析:非懒加载的单例Bean初始化过程(上)》,分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的。先贴一下AbstractAutowireCapableBeanFactory的doCreateBean方法代码:


protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

    // Instantiate the bean.

    BeanWrapper instanceWrapper = null;

    if (mbd.isSingleton()) {

        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);

    }

    if (instanceWrapper == null) {

        instanceWrapper = createBeanInstance(beanName, mbd, args);

    }

    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);

    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

 

    // Allow post-processors to modify the merged bean definition.

    synchronized (mbd.postProcessingLock) {

        if (!mbd.postProcessed) {

            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

            mbd.postProcessed = true;

        }

    }

 

    // Eagerly cache singletons to be able to resolve circular references

    // even when triggered by lifecycle interfaces like BeanFactoryAware.

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

            isSingletonCurrentlyInCreation(beanName));

    if (earlySingletonExposure) {

        if (logger.isDebugEnabled()) {

            logger.debug("Eagerly caching bean '" + beanName +

                    "' to allow for resolving potential circular references");

        }

        addSingletonFactory(beanName, new ObjectFactory() {

            public Object getObject() throws BeansException {

                return getEarlyBeanReference(beanName, mbd, bean);

            }

        });

    }

 

    // Initialize the bean instance.

    Object exposedObject = bean;

    try {

        populateBean(beanName, mbd, instanceWrapper);

        if (exposedObject != null) {

            exposedObject = initializeBean(beanName, exposedObject, mbd);

        }

    }

    catch (Throwable ex) {

        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {

            throw (BeanCreationException) ex;

        }

        else {

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);

        }

    }

 

    if (earlySingletonExposure) {

        Object earlySingletonReference = getSingleton(beanName, false);

        if (earlySingletonReference != null) {

            if (exposedObject == bean) {

                exposedObject = earlySingletonReference;

            }

            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

                String[] dependentBeans = getDependentBeans(beanName);

                Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);

                for (String dependentBean : dependentBeans) {

                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

                        actualDependentBeans.add(dependentBean);

                    }

                }

                if (!actualDependentBeans.isEmpty()) {

                    throw new BeanCurrentlyInCreationException(beanName,

                            "Bean with name '" + beanName + "' has been injected into other beans [" +

                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +

                            "] in its raw version as part of a circular reference, but has eventually been " +

                            "wrapped. This means that said other beans do not use the final version of the " +

                            "bean. This is often the result of over-eager type matching - consider using " +

                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");

                }

            }

        }

    }

 

    // Register bean as disposable.

    try {

        registerDisposableBeanIfNecessary(beanName, bean, mbd);

    }

    catch (BeanDefinitionValidationException ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);

    }

 

    return exposedObject;

}


下面继续分析初始化一个Bean的流程,不太重要的流程就跳过了。


属性注入


属性注入的代码比较好找,可以看一下40行,取名为populateBean,即填充Bean的意思,看一下代码实现:


protected void populateBean(String beanName, AbstractBeanDefinition 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;

                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);

        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) {

            checkDependencies(beanName, mbd, filteredPds, pvs);

        }

    }

 

    applyPropertyValues(beanName, mbd, bw, pvs);

}


这段代码层次有点深,跟一下74行的applyPropertyValues方法,最后那个pvs的实现类为MutablePropertyValues,里面持有一个List,每一个PropertyValue包含了此Bean属性的属性名与属性值。74行的代码实现为:


protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {

    if (pvs == null || pvs.isEmpty()) {

        return;

    }

 

    MutablePropertyValues mpvs = null;

    List original;

 

    if (System.getSecurityManager()!= null) {

        if (bw instanceof BeanWrapperImpl) {

            ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());

        }

    }

 

    if (pvs instanceof MutablePropertyValues) {

        mpvs = (MutablePropertyValues) pvs;

        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 {

        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 deepCopy = new ArrayList(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);

    }

}


之后在第41行~第76行做了一次深拷贝(只是名字叫做深拷贝而已,其实就是遍历PropertyValue然后一个一个赋值到一个新的List而不是Java语义上的Clone,这里使用深拷贝是为了解析Values值中的所有引用),将PropertyValue一个一个赋值到一个新的List里面去,起名为deepCopy。最后执行83行进行复制,bw即BeanWrapper,持有Bean实例的一个Bean包装类,看一下代码实现:


public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)

        throws BeansException {

 

    List propertyAccessExceptions = null;

    List propertyValues = (pvs instanceof MutablePropertyValues ?

            ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));

    for (PropertyValue pv : propertyValues) {

        try {

            // This method may throw any BeansException, which won't be caught

            // here, if there is a critical failure such as no matching field.

            // We can attempt to deal only with less serious exceptions.

            setPropertyValue(pv);

        }

        catch (NotWritablePropertyException ex) {

            if (!ignoreUnknown) {

                throw ex;

            }

            // Otherwise, just ignore it and continue...

        }

        catch (NullValueInNestedPathException ex) {

            if (!ignoreInvalid) {

                throw ex;

            }

            // Otherwise, just ignore it and continue...

        }

        catch (PropertyAccessException ex) {

            if (propertyAccessExceptions == null) {

                propertyAccessExceptions = new LinkedList();

            }

            propertyAccessExceptions.add(ex);

        }

    }

 

    // If we encountered individual exceptions, throw the composite exception.

    if (propertyAccessExceptions != null) {

        PropertyAccessException[] paeArray =

                propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);

        throw new PropertyBatchUpdateException(paeArray);

    }

}


这段代码没什么特别的,遍历前面的deepCopy,拿每一个PropertyValue,执行第12行的setPropertyValue:


public void setPropertyValue(PropertyValue pv) throws BeansException {

    PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;

    if (tokens == null) {

        String propertyName = pv.getName();

        BeanWrapperImpl nestedBw;

        try {

            nestedBw = getBeanWrapperForPropertyPath(propertyName);

        }

        catch (NotReadablePropertyException ex) {

            throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,

                    "Nested property in path '" + propertyName + "' does not exist", ex);

        }

        tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));

        if (nestedBw == this) {

            pv.getOriginalPropertyValue().resolvedTokens = tokens;

        }

        nestedBw.setPropertyValue(tokens, pv);

    }

    else {

        setPropertyValue(tokens, pv);

    }

}


找一个合适的BeanWrapper,这里就是自身,然后执行17行的setPropertyValue方法进入最后一步,方法非常长,截取核心的一段:


final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?

    ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :

    pd.getWriteMethod());

    if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {

    if (System.getSecurityManager()!= null) {

        AccessController.doPrivileged(new PrivilegedAction() {

                public Object run() {

                    writeMethod.setAccessible(true);

                    return null;

                }

            });

        }

        else {

            writeMethod.setAccessible(true);

        }

    }

    final Object value = valueToApply;

    if (System.getSecurityManager() != null) {

    try {

        AccessController.doPrivileged(new PrivilegedExceptionAction() {

            public Object run() throws Exception {

                writeMethod.invoke(object, value);

                return null;

            }

        }, acc);

    }

    catch (PrivilegedActionException ex) {

        throw ex.getException();

    }

}

else {

    writeMethod.invoke(this.object, value);

}


大致流程就是两步:


(1)拿到写方法并将方法的可见性设置为true


(2)拿到Value值,对Bean通过反射调用写方法


这样完成了对于Bean属性值的设置。


看完本文有收获?请转发分享给更多人

关注「ImportNew」,看技术干货