www.allbetgame.us:Spring IoC 属性赋值阶段

admin 2个月前 (07-21) 科技 38 1

前言

本系列所有基于 Spring 5.2.2.BUILD-SNAPSHOT 版本。由于 Spring 整个系统太过于重大,以是只会举行要害部门的源码剖析。

本篇文章主要先容 Spring IoC 容器中 bean 的属性赋值阶段。

正文

我们在Spring IoC bean 的建立一文中剖析建立 bean 实例的主要流程,此时建立出来的 bean 照样个属性未赋值的实例,在建立完之后会进入 populateBean() 方式,即进入属性赋值阶段。我们简朴回首一下,上次剖析过的 doCreateBean() 方式:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throWs BeanCreatIZ*ONException {

    // 实例化 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);
    } 
    // 省略部门代码
}

属性赋值

AbstractAutowireCapableBeanFactory#populateBean

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(),否则直接使用返回的 PropertyValuespostProcessPropertyValues() 若是返回空会直接跳过属性填充阶段,不为空直接使用返回的 PropertyValues

根据名称依赖注入

AbstractAutowireCapableBeanFactory#autowireByName

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() 方式去获取实例,完成注入。

非简朴类型就是指除去8个原始类型、String类型、Number类型、Date类型、URL类型、URI类型的其它类型。

registerDependentBean() 方式在Spring IoC bean 的加载一文中有剖析过,这里不再赘述。

根据类型依赖注入

AbstractAutowireCapableBeanFactory#autowireByType

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 的建立一文中先容过,这里不再赘述。

属性赋值

AbstractAutowireCapableBeanFactory#applyPropertyValues

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() 方式,如下:

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 方式:

注重:没有 setter 方式时会抛出异常。

总结

本篇文章主要剖析了 Spring IoC 的属性赋值阶段的流程,Spring 在此阶段也提供了2个扩展点;分别是 bean 的实例化后和属性赋值前,即 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation() 方式和 postProcessProperties() 方式。需要注重的是在 XML 中设置的 autowire 属性,不管是 byName 照样 byType 都需要 setter 方式,然则我们平时在使用 @Autowire 注解时并不需要 settter 方式,缘故原由会在剖析 @Autowire 注解时讲述。

最后,我模拟 Spring 写了一个精简版,代码会连续更新。地址:https://github.com/leisurexi/tiny-spring。

,

欧博电脑版下载

欢迎进入博电脑版下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

Allbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:www.allbetgame.us:Spring IoC 属性赋值阶段

网友评论

  • (*)

最新评论

  • 环球UG注册 2020-07-21 00:11:45 回复

    Allbetwww.aLLbetgame.us欢迎进入Allbet平台(Allbet Gaming):www.aLLbetgame.us,欧博平台开放欧博(Allbet)开户、欧博(Allbet)代理开户、欧博(Allbet)电脑客户端、欧博(Allbet)APP下载等业务。老读者赞一个

    1

文章归档

站点信息

  • 文章总数:488
  • 页面总数:0
  • 分类总数:8
  • 标签总数:860
  • 评论总数:184
  • 浏览总数:2827