bean的创建第三部分 bean工厂方法参数的解析

Posted honger

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bean的创建第三部分 bean工厂方法参数的解析相关的知识,希望对你有一定的参考价值。

准备好一系列参数之后,开始参数类型的转换,方法参数的对应。
ConstructorResolver.createArgumentArray

private ArgumentsHolder createArgumentArray(
            String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues,
            BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
            boolean autowiring) throws UnsatisfiedDependencyException {

        String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
//获取类型转换器    
    TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
                this.beanFactory.getCustomTypeConverter() : bw);

        ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
//用于储存可以使用的参数
        Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
                new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
        Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);

        for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
            Class<?> paramType = paramTypes[paramIndex];
            String paramName = (paramNames != null ? paramNames[paramIndex] : null);
            // Try to find matching constructor argument value, either indexed or generic.
 //尝试从indexed和generic集合中寻找符合条件的参数,indexed可以根据参数下标获取,没有指定下标的可以更具参数名或者参数的类型去获取。
            ConstructorArgumentValues.ValueHolder valueHolder =
                    resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
            // If we couldn‘t find a direct match and are not supposed to autowire,
            // let‘s try the next generic, untyped argument value as fallback:
            // it could match after type conversion (for example, String -> int).
//如果没有找到,使用通过的值,什么都没有指定的,就指定了一个值的参数
            if (valueHolder == null && !autowiring) {
                valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
            }
            if (valueHolder != null) {
                // We found a potential match - let‘s give it a try.
                // Do not consider the same value definition multiple times!
//如果找了对应的参数,那么保存到usedValueHolders集合中
                usedValueHolders.add(valueHolder);
//获取原始的值,这个值可能是某个bean,还没有进行类型转换
                Object originalValue = valueHolder.getValue();
                Object convertedValue;
//如果已经进行了转换的,存入预备参数中
                if (valueHolder.isConverted()) {
                    convertedValue = valueHolder.getConvertedValue();
                    args.preparedArguments[paramIndex] = convertedValue;
                }
                else {
//如果没有被转换过,那么就进行类型转换
                    ConstructorArgumentValues.ValueHolder sourceHolder =
                            (ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
//获取最原始的值,比如一个BeanRuntimeReference。
                    Object sourceValue = sourceHolder.getValue();
                    try {
                        convertedValue = converter.convertIfNecessary(originalValue, paramType,
                                MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
                        // TODO re-enable once race condition has been found (SPR-7423)
                        /*
//如果最原始的值和经过解析后的参数一致,那么就将最原始的ValueHolder的已转换的值设置成类型转换后的值,表示这个转化后的值就是通过当前valueholder的值转化后的值,并把转化后的值设置都预备参数数组中,值得注意的是,这段代码被注释掉了
                        if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
                            // Either a converted value or still the original one: store converted value.
                            sourceHolder.setConvertedValue(convertedValue);
                            args.preparedArguments[paramIndex] = convertedValue;
                        }
                        else {
                        */
//标记参数已经被解析,并将最原始的值设置给了预备参数集合
                            args.resolveNecessary = true;
                            args.preparedArguments[paramIndex] = sourceValue;
                        // }
                    }
                    catch (TypeMismatchException ex) {
                        throw new UnsatisfiedDependencyException(
                                mbd.getResourceDescription(), beanName, paramIndex, paramType,
                                "Could not convert " + methodType + " argument value of type [" +
                                ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
                                "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
                    }
                }
//保存类型转换后的参数,和未进行类型转换的参数
                args.arguments[paramIndex] = convertedValue;
                args.rawArguments[paramIndex] = originalValue;
            }

//如果没有找到匹配的参数,那么就进行自动装配,自动装配通过参数类型去BeanFactory去寻找符合类型的bean或者是用@Value注解修饰的
            else {
                // No explicit match found: we‘re either supposed to autowire or
                // have to fail creating an argument array for the given constructor.
                if (!autowiring) {
                    throw new UnsatisfiedDependencyException(
                            mbd.getResourceDescription(), beanName, paramIndex, paramType,
                            "Ambiguous " + methodType + " argument types - " +
                            "did you specify the correct bean references as " + methodType + " arguments?");
                }
                try {
                    MethodParameter param = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
//自动装配,这里和对preparedArguments参数的自动装配是一样的解析方法。
                    Object autowiredArgument = resolveAutowiredArgument(param, beanName, autowiredBeanNames, converter);
                    args.rawArguments[paramIndex] = autowiredArgument;
                    args.arguments[paramIndex] = autowiredArgument;
//标记这个参数是通过自动装配获取的
                    args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
                    args.resolveNecessary = true;
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(
                            mbd.getResourceDescription(), beanName, paramIndex, paramType, ex);
                }
            }
        }
//注册依赖,记录当前beanName依赖的bean的name,用于检测循环依赖
        for (String autowiredBeanName : autowiredBeanNames) {
            this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
            if (this.beanFactory.logger.isDebugEnabled()) {
                this.beanFactory.logger.debug("Autowiring by type from bean name ‘" + beanName +
                        "‘ via " + methodType + " to bean named ‘" + autowiredBeanName + "‘");
            }
        }

        return args;
    }

 

以上是关于bean的创建第三部分 bean工厂方法参数的解析的主要内容,如果未能解决你的问题,请参考以下文章

Spring的bean管理(XML方式)

bean 实例化原理解析

Spring关于Bean

Spring三种实例化Bean的方式

创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是

spring学习-IOC-基于XML的Bean创建2