0
点赞
收藏
分享

微信扫一扫

[Spring]Spring是如何做Bean属性填充的-populateBean

前言

在前面的doCreateBean方法中,我们了解到,populateBean是负责填充Bean实例属性的。此时Bean中需要依赖注入的成员已经在applyMergedBeanDefinitionPostProcessors中被对应的后置处理器进行了存储,最终的成员被封装到了AutowiredAnnotationBeanPostProcessor#injectionMetadataCache这个集合中.

1. Dependencies和Dependency Injection

很多人可能还不清除什么是依赖和依赖注入.这是理解Spring IoC的一个核心概念.下面简单从代码的角度谈谈什么是依赖和依赖注入.

  • 一个简单的MVC登陆入口
@RestController
@RequestMapping("/web")
public class UserController {

    @Autowired
    @Qualifier("normalUserService")
    private UserService userService;

    /**
     * 用户登陆入口
     */
    @PostMapping("/login")
    public void login(User user) {
        userService.login(user);
    }
}

2. 自动装配

3. populateBean的总体流程

  • 激活InstantiationAwareBeanPostProcessor后置处理器的InstantiationAwareBeanPostProcessor方法: 在实例化bean之后,Spring属性填充之前执行的钩子方法,
    这是在Spring的自动装配开始之前对该bean实例执行自定义字段注入的回调,也是最后一次机会在自动装配前修改Bean的属性值。
  • 解析依赖注入的方式,将属性装配到PropertyValues中: resolvedAutowireMode.
  • 激活InstantiationAwareBeanPostProcessor#postProcessProperties: 对@AutoWired标记的属性进行依赖注入.
  • 依赖检查: checkDependencies.
  • 将解析的值用BeanWrapper进行包装: applyPropertyValues.
3.1 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
  • AbstractAutowireCapableBeanFactory#populateBean
        // InstantiationAwareBeanPostProcessors最后一次进行对bean的属性修改
        // 采用职责链的方式对所有实现了InstantiationAwareBeanPostProcessor的后置处理器调用.
        // 直到某个InstantiationAwareBeanPostProcessor在postProcessAfterInstantiation中返回了false
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 如果返回了false,直接中断,不进行下面的操作
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }
        }
3.2 根据注入方式解析属性到PropertyValues
        // 这里的pvs其实是一个MutablePropertyValues实例
        // 提供对属性的读写操作实现,同时可以通过构造函数实现深拷贝
        // 获取BeanDefinition里面为Bean设置的属性值
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        // 根据Bean配置的依赖注入方式完成注入,默认是0,即不走以下逻辑
        // 如果设置了相关的依赖装配方式,会遍历Bean的属性,根据type或者name完成相应注入
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            // 根据beanName进行autowired自动装配逻辑
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            // 根据Type进行autowired自动装配逻辑
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }
resolvedAutowireMode 依赖注入方式 描述
0 AUTOWIRE_NO 没有显式配置上装配的方式
1 AUTOWIRE_BY_NAME 按beanName进行装配
2 AUTOWIRE_BY_TYPE 按type进行装配
3 AUTOWIRE_CONSTRUCTOR 在构造函数中进行装配
4 AUTOWIRE_AUTODETECT 通过内省bean类确定适当的自动装配策略,Spring已经将其标注为@Deprecated
    @Bean(autowire = Autowire.BY_NAME)
3.3 InstantiationAwareBeanPostProcessor#postProcessProperties
        // 容器是否注册了InstantiationAwareBeanPostProcessors
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        // 是否进行依赖检查,默认为false
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 对@AutoWired标记的属性进行依赖注入
                    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);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
  • AutowiredAnnotationBeanPostProcessor#postProcessProperties
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        // 获取指定类中被@Autowired注解标记的metadata.
        // metadata在实例化后的applyMergedBeanDefinitionPostProcessors中进行了存储
        // 此时的findAutowiringMetadata是从injectionMetadataCache缓存中读取metadata
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            // 对Bean的属性进行自动注入
            metadata.inject(bean, beanName, pvs);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }
3.3.1 org.springframework.beans.factory.annotation.InjectionMetadata#inject
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectedElement> elementsToIterate =
                (checkedElements != null ? checkedElements : this.injectedElements);
        if (!elementsToIterate.isEmpty()) {
            for (InjectedElement element : elementsToIterate) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Processing injected element of bean '" + beanName + "': " + element);
                }
                // 调用InjectedElement#inject,这里是多态的实现
                // @Autowired关注AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject
                element.inject(target, beanName, pvs);
            }
        }
    }
  • AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            // 当前存储的需要注入的成员
            Field field = (Field) this.member;
            Object value;
            // 如果该成员的值被缓存了,从缓存中获取
            if (this.cached) {
                // 最终调用DefaultListableBeanFactory的resolveDependency
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            }
            else {
                // 为该成员创建一个DependencyDescriptor.
                DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                // 设置当前bean的Class
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
                Assert.state(beanFactory != null, "No BeanFactory available");
                // 获取类型转换器
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                try {
                    // 最终调用DefaultListableBeanFactory的resolveDependency
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                }
                synchronized (this) {
                    // 如果成员变量的值没有缓存
                    if (!this.cached) {
                        // 成员变量的值不为null,并且required==true
                        if (value != null || this.required) {
                            this.cachedFieldValue = desc;
                            // 注册依赖关系
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                // 依赖对象类型和字段类型匹配,默认按类型注入
                                if (beanFactory.containsBean(autowiredBeanName) &&
                                        beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                    this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                            desc, autowiredBeanName, field.getType());
                                }
                            }
                        }
                        else {
                            this.cachedFieldValue = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                // 调用反射进行赋值
                field.set(bean, value);
            }
        }
    }
3.3.2 DefaultListableBeanFactory#resolveDependency
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

        descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return createOptionalDependency(descriptor, requestingBeanName);
        }
        else if (ObjectFactory.class == descriptor.getDependencyType() ||
                ObjectProvider.class == descriptor.getDependencyType()) {
            return new DependencyObjectProvider(descriptor, requestingBeanName);
        }
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
        }
        else {
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                    descriptor, requestingBeanName);
            if (result == null) {
                // 解析依赖
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }
  • DefaultListableBeanFactory#doResolveDependency
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
        try {
            // 从容器中获取依赖,在debug环境下点进去会发现,会到达beanFactory.getBean()中
            Object shortcut = descriptor.resolveShortcut(this);
            // 如果可以从容器中获取到bean,直接返回
            if (shortcut != null) {
                return shortcut;
            }

            Class<?> type = descriptor.getDependencyType();
            // 处理@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());
                try {
                    return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
                }
                catch (UnsupportedOperationException ex) {
                    // A custom TypeConverter which does not support TypeDescriptor resolution...
                    return (descriptor.getField() != null ?
                            converter.convertIfNecessary(value, type, descriptor.getField()) :
                            converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
                }
            }
            // 如果标识@Autowired注解的成员变量是复合类型,如:数组、List、Map等.
            // 从这里获取@Autowired中的值
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                return multipleBeans;
            }
            // 如果被@Autowired标注的成员并非复合对象
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                // 如果找不到,校验当前是否标注了required为true.
                if (isRequired(descriptor)) {
                    // 如果@Autowired标注了(required = true),但是无法匹配到相应的bean,抛出NoSuchBeanDefinitionException异常
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                return null;
            }

            String autowiredBeanName;
            Object instanceCandidate;
            // 如果匹配到了不止一个Bean,看看是否标注了@Primary和@Priority
            if (matchingBeans.size() > 1) {
                autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                        // 如果没有声明,则直接抛出NoUniqueBeanDefinitionException
                        return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                    }
                    else {
                        // In case of an optional Collection/Map, silently ignore a non-unique case:
                        // possibly it was meant to be an empty collection of multiple regular beans
                        // (before 4.3 in particular when we didn't even look for collection beans).
                        return null;
                    }
                }
                instanceCandidate = matchingBeans.get(autowiredBeanName);
            }
            else {
                // We have exactly one match.
                Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
                // key为被依赖的候选者名称,例如:UserController依赖UserService.
                // 此时autowiredBeanName=userService
                autowiredBeanName = entry.getKey();
                // Class,先选举,选举结束之后再进行实例化
                instanceCandidate = entry.getValue();
            }

            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(autowiredBeanName);
            }
            if (instanceCandidate instanceof Class) {
                // 将获取到的候选者Class进行getBean
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
            }
            Object result = instanceCandidate;
            if (result instanceof NullBean) {
                if (isRequired(descriptor)) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                result = null;
            }
            if (!ClassUtils.isAssignableValue(type, result)) {
                throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
            }
            return result;
        }
        finally {
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }
    }
3.3.3 如果Autowired按byType的方式无法挑选出最合适的Bean如何进行降级处理
  • DefaultListableBeanFactory#determineAutowireCandidate
    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        // 根据@Primary注解标签来选择最优解
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }
        // 根据@Order、@Priority以及实现了Order接口的序号来最合适的Bean(序号越小越合适)进行注入
        String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        }
        // Fallback
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateName = entry.getKey();
            Object beanInstance = entry.getValue();
            // 如果无法通过上面两个方法找到最优解的Bean:
            // 如果类型已经在resolvableDependencies中,直接返回已经注册的对象.
            // 如果byType的方式找不到,尝试使用byName的方式寻找依赖
            // 如果属性名称和某个候选者的Bean名称或者别名一致,则直接将该Bean返回
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }
@Autowired
UserService vip;

4. 依赖检查

5. 将解析的值用BeanWrapper进行包装-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;
            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<>(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);
        }
    }

    /**
     * Convert the given value for the specified target property.
     */
    @Nullable
    private Object convertForProperty(
            @Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {

        if (converter instanceof BeanWrapperImpl) {
            return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
        }
        else {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
        }
    }

总结

  1. 注解驱动的Bean执行属性填充并不在autowireByNameautowireByType中,而是在AutowiredAnnotationBeanPostProcessor这个后置处理器的postProcessProperties中.
  2. 在做属性填充时,如果当前的Bean实例依赖的成员(另一个Bean)未被加载,会进入选举候选名单的逻辑中,进行各种判断后,选出最适合的Bean实例进行getBean操作.
  3. @Autowired在进行自动装配的过程中,默认按照"byType"的方式进行Bean加载,如果出现无法挑选出合适的Bean的情况,再将属性名与候选Bean名单中的beanName进行对比.
  4. 正确地声明@PrimaryOrder等注解让Bean在多态的选举中优选胜出.
  5. required=false可以让程序在找不到Bean的时候不抛出异常,但是调用期间还是会报错(缓兵之计),不建议这种使用.
  6. XML的自动装配模式与注解驱动的模式在代码上是不同的分岔.
举报

相关推荐

0 条评论