【spring源码分析】加载bean过程(2)

来源:互联网 发布:海上钢琴师知乎 编辑:程序博客网 时间:2024/06/08 01:56

在上文【spring源码分析】加载bean过程(1),分析了单例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<Object>() {                @Override                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<String> actualDependentBeans = new LinkedHashSet<String>(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;    }

属性注入

可以看到第41行代码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;                    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) {                checkDependencies(beanName, mbd, filteredPds, pvs);            }        }        applyPropertyValues(beanName, mbd, bw, pvs);    }

先看下36-71行,是对于AutoWired,Resource等自动注入的处理。重点是autowireByName,autowireByType,ibp.postProcessPropertyValues方法,先通过名称或者类型获取相应的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;            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<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);        }    }

第41-63行,对于属性遍历做一次深层复制,其实就只是对于属性List添加
到一个新的List中,是为了能解析所有属性的引用。看一下第83行的代码

    @Override    public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)            throws BeansException {        List<PropertyAccessException> propertyAccessExceptions = null;        List<PropertyValue> 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<PropertyAccessException>();                }                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);        }    }

第13行setPropertyValue方法

    @Override    public void setPropertyValue(String propertyName, Object value) throws BeansException {        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);        }        PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));        nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));    }

最后看一下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<Object>() {                            @Override                            public Object run() {                                writeMethod.setAccessible(true);                                return null;                            }                        });                    }                    else {                        writeMethod.setAccessible(true);                    }                }

主要的流程:
(1)拿到写方法并将方法的可见性设置为true

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

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

Aware注入

回到doCreateBean方法的第43行initializeBean(beanName, exposedObject, mbd)方法,对于bean进行一些初始化处理。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {        if (System.getSecurityManager() != null) {            AccessController.doPrivileged(new PrivilegedAction<Object>() {                @Override                public Object run() {                    invokeAwareMethods(beanName, bean);                    return null;                }            }, getAccessControlContext());        }        else {            invokeAwareMethods(beanName, bean);        }        Object wrappedBean = bean;        if (mbd == null || !mbd.isSynthetic()) {            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);        }        try {            invokeInitMethods(beanName, wrappedBean, mbd);        }        catch (Throwable ex) {            throw new BeanCreationException(                    (mbd != null ? mbd.getResourceDescription() : null),                    beanName, "Invocation of init method failed", ex);        }        if (mbd == null || !mbd.isSynthetic()) {            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);        }        return wrappedBean;    }

看一下上面第5行的实现:

    private void invokeAwareMethods(final String beanName, final Object bean) {        if (bean instanceof Aware) {            if (bean instanceof BeanNameAware) {                ((BeanNameAware) bean).setBeanName(beanName);            }            if (bean instanceof BeanClassLoaderAware) {                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());            }            if (bean instanceof BeanFactoryAware) {                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);            }        }    }

在使用Spring的时候我们将自己的Bean实现BeanNameAware接口、BeanFactoryAware接口等,依赖容器帮我们注入当前Bean的名称或者Bean工厂。如果bean是BeanNameAware接口的实现类会调用setBeanName方法、如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。

postProcessBeforeInitialization方法

上面initializeBean方法再看17行其实现:

    @Override    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)            throws BeansException {        Object result = existingBean;        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {            result = beanProcessor.postProcessBeforeInitialization(result, beanName);            if (result == null) {                return result;            }        }        return result;    }

遍历每个BeanPostProcessor接口实现,调用postProcessBeforeInitialization方法

调用初始化方法

还是上面initializeBean方法,再看21行其实现:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)            throws Throwable {        boolean isInitializingBean = (bean instanceof InitializingBean);        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {            if (logger.isDebugEnabled()) {                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");            }            if (System.getSecurityManager() != null) {                try {                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {                        @Override                        public Object run() throws Exception {                            ((InitializingBean) bean).afterPropertiesSet();                            return null;                        }                    }, getAccessControlContext());                }                catch (PrivilegedActionException pae) {                    throw pae.getException();                }            }            else {                ((InitializingBean) bean).afterPropertiesSet();            }        }        if (mbd != null) {            String initMethodName = mbd.getInitMethodName();            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&                    !mbd.isExternallyManagedInitMethod(initMethodName)) {                invokeCustomInitMethod(beanName, bean, mbd);            }        }    }

这里做了2件事:

1.判断bean是否实现InitializingBean,如果是的话强制转换为InitializingBean,调用afterPropertiesSet方法。

2.取bean配置的init-method方法,如果有的话通过反射调用。

调用postProcessAfterInitialization方法

依然是上面initializeBean方法,再看29行其实现:

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)            throws BeansException {        Object result = existingBean;        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {            result = beanProcessor.postProcessAfterInitialization(result, beanName);            if (result == null) {                return result;            }        }        return result;    }    @Override    public void destroyBean(Object existingBean) {        new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();    }

注册销毁方法

见最初doCreateBean的registerDisposableBeanIfNecessary(beanName, bean, mbd);

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {        AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {            if (mbd.isSingleton()) {                // Register a DisposableBean implementation that performs all destruction                // work for the given bean: DestructionAwareBeanPostProcessors,                // DisposableBean interface, custom destroy method.                registerDisposableBean(beanName,                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));            }            else {                // A bean with a custom scope...                Scope scope = this.scopes.get(mbd.getScope());                if (scope == null) {                    throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");                }                scope.registerDestructionCallback(beanName,                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));            }        }    }

注册销毁方法需要满足的条件:
1.如果bean是DisposableBean的实现类,调用destroy()方法

2.如果bean有配置destroy-method属性,则调用对应的方法

满足上述条件之一,便会注册该bean的销毁方法。

总结

最后用一张图总结一下spring初始化bean的过程:
这里写图片描述

原创粉丝点击