zoukankan      html  css  js  c++  java
  • 属性注入

    前言

    上一篇文章创建bean讲述了创建bean的第一二个步骤,这篇文章接着讲述创建bean的第三个步骤----属性注入。

    属性注入

    在了解循环依赖和创建bean的时候,我们曾经经常反复的提到了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比如:可以用来支持属性注入的类型
            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;
            }
    
            PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    
            if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
                //根据名称自动注入
                if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
                    autowireByName(beanName, mbd, bw, newPvs);
                }
                //根据类型自动注入
                if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                    autowireByType(beanName, mbd, bw, newPvs);
                }
                pvs = newPvs;
            }
            //后处理器已经初始化
            boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
            //需要依赖检查
            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;
                        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;
                    }
                }
            }
            if (needsDepCheck) {
                //依赖检查,对应depends-on属性,3.0已经弃用此属性
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
    
            if (pvs != null) {
                //将属性应用到bean中
                applyPropertyValues(beanName, mbd, bw, pvs);
            }
        }

     分析上述代码的逻辑:

    (1)InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数的应用,此函数可以控制程序是否继续进行属性填充;

    (2)根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中;

    (3)应用InstantiationAwareBeanPostProcessor处理器postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证;

    (4)将所有PropertyValues中的属性填充至BeanWrapper中。

     将上述代码中的重点方法再进行进一步的分析:

    1.autowireByName(根据名称注入)

    protected void autowireByName(
                String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
            //寻找bw中需要依赖注入的属性
            String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
            for (String propertyName : propertyNames) {
                if (containsBean(propertyName)) {
                    //递归初始化相关的bean
                    Object bean = getBean(propertyName);
                    pvs.add(propertyName, bean);
                    //注册依赖
                    registerDependentBean(propertyName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("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");
                    }
                }
            }
        }

     上述代码并没有什么复杂的逻辑:在传入的参数pvs中找出已经加载的bean,并递归实例化,进而加入到pvs中。

    2.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);
            //寻找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 != 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.isInstance(bw.getWrappedInstance());
                        DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                        //解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowireBeanNames中
                        Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                        if (autowiredArgument != null) {
                            pvs.add(propertyName, autowiredArgument);
                        }
                        for (String autowiredBeanName : autowiredBeanNames) {
                            //注册依赖
                            registerDependentBean(autowiredBeanName, beanName);
                            if (logger.isTraceEnabled()) {
                                logger.trace("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, @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;
            }
        }
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
            InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
            try {
                Object shortcut = descriptor.resolveShortcut(this);
                if (shortcut != null) {
                    return shortcut;
                }
    
                Class<?> type = descriptor.getDependencyType();
                //用于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()));
                }
    
                Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
                if (multipleBeans != null) {
                    return multipleBeans;
                }
                //根据属性类型找到BeanFactory中所有类型匹配的bean,返回值的构成为:key=匹配的beanName,value=beanName对应的实例化后的bean
                Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
                if (matchingBeans.isEmpty()) {
                    //根据autowire的require属性为true而找到的匹配项却为空则只能抛出异常
                    if (isRequired(descriptor)) {
                        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    return null;
                }
    
                String autowiredBeanName;
                Object instanceCandidate;
    
                if (matchingBeans.size() > 1) {
                    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                    if (autowiredBeanName == null) {
                        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                            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();
                    autowiredBeanName = entry.getKey();
                    instanceCandidate = entry.getValue();
                }
    
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.add(autowiredBeanName);
                }
                if (instanceCandidate instanceof Class) {
                    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);
            }
        }
    doResolveDependency

    只是大致上说一下上述代码的处理流程:

      寻找类型的匹配执行顺序时,首先尝试使用解析器进行解析,如果解析器没有成功解析,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合等类型来说并不在解析范围之内,所以再次对不同类型进行不同情况的处理,虽说对于不同类型的处理方式不一样,但是大致的思路还是很相似的,所以函数中只对数组类型进行了详细的注释。

    3.applyPropertyValues 

     程序运行到这里,已经完成了对所有属性的获取,但是获取的属性还是以PropertyValues形式存在的,还并没有应用到已经实例化的bean中,这一工作是在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;
                //如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanWrapper中
                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<>(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);
                    }
                    // 可能在合并bean定义中存储转换后的值,
                    //为了避免对每个创建的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();
            }
    
            // 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);
            }
        }

     参考:《Spring源码深度解析》 郝佳 编著:

    作者:Joe
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    Oracle 10g 体系结构及安全管理
    Oracle 10g数据库概述
    jQuery Ajax应用
    ASP.NET Ajax核心对象
    ASP.NET XML
    jQuery插件的使用和编写
    jQuery中的Ajax应用
    弹窗下面的页面滚动问题
    报文过长,华为手机自动拦截报文
    手机抓包 配置步骤
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/10181835.html
Copyright © 2011-2022 走看看