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;
    }

原文地址:https://www.cnblogs.com/honger/p/10389856.html

时间: 2024-11-08 04:49:31

bean的创建(五)第三部分 bean工厂方法参数的解析的相关文章

浅析设计模式(四)——创建型模式之simple-factory(简单工厂方法,非设计模式)

简单工厂方法simple-factory 注:部分内容参考自<Head First设计模式>和GoF<设计模式:可复用面向对象软件的基础> 首先需要说明的是:简单工厂方法不是一种设计模式,它更像是一种编程习惯. 定义:简单工厂方法把变化的部分(即创建对象的细节)封装起来,即通过工厂类(Factory)来处理创建对象的细节. 这种处理方式把创建对象的细节进行了简单的封装,单独进行管理,使之解耦,便于维护. 例如:要创建不同类型的Pizza,我们不在PizzaStore的方法中直接根据

创建多个“产品”的方式——工厂方法模式总结

简单工厂模式严格来说不算一个设计模式——缺点 继续说之前提到的简单工厂模式,严格来说,这不算一个设计模式……而且在业务量比较多了之后,它也有诸多的隐患 1.由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连 2.由于简单工厂模式的产品基于一个共同的抽象类或者接口,这样一来,产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,简单工厂类就需要维护大量的if-else判断,比如导入导出功能,虽然可以用反射或者配置文件,注解等解耦,但是还有更好的办法.

创建和销毁对象——用静态工厂方法代替构造器

参考资料:<Effective Java>,https://www.jianshu.com/p/ceb5ec8f1174. 基础回顾 1.什么是构造器? 构造器与类同名,在新建一个类的对象时,构造器会运行,以便将实例初始化为所希望的状态. 每个类都会有一个默认的无参的构造器.也可以自己手动写一个构造器. 如,在People类中写一个构造器: public People(String Name,int Age) { this.Name=Name; this.Age=Age; } 然后新建一个关于

(创建型模式三)抽象工厂模式

package com.eyugame.modle; /** * 抽象工厂模式 * * @author JYC506 * */ public class MyFactory implements IAbstractFactory { @Override public IProduct1 createIProduct1() { return new Product1(); } @Override public IProduct2 createIProduct2() { return new Pro

创建型设计模式(一)工厂方法模式

一.一句话背景 我需要一辆汽车,那我可以直接从工厂里面提货,而不用去管汽车是怎么做出来的,以及生产汽车的具体实现,我只需要告诉这个工厂要生产什么品牌的汽车就好,具体的汽车生产流水线我也不用管. 二.使用场景 知道部分特性而创建具体对象的场景. 如:根据环境类型(dev,test或master等)直接调用一整套环境配置 三.模型分析 生产流水线:接口,定义了生产汽车的方法 具体产品的生产流水线:类,里面的方法帮我们创建具体的类对象(汽车),生产流水线接口的具体实现 工厂:类,需要根据客户需求调用不

Spring IOC 容器源码分析 - getBean调用方法解析(三) -- 实例化 Bean 对象

1. createBeanInstance protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 解析 bean ,将 bean 类名解析为 class 引用 Class<?> beanClass = resolveBeanClass(mbd, beanName); /* * 检测类的访问权限.默认情况下,对于非 public

Spring 通过工厂方法(Factory Method)来配置bean

Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. 在第一种利用bean config file(spring xml)方式中, 还包括如下三小类 反射模式 工厂方法模式(本文重点) Factory Bean模式 其中反射模式最常见, 我们需要在bean 配置中指明我们需要的bean object的全类名. 例如: <bean id="car1

Spring(十三):使用工厂方法来配置Bean的两种方式(静态工厂方法&amp;实例工厂方法)

通过调用静态工厂方法创建Bean 1)调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不需要关心创建对象的具体细节. 2)要声明通过静态方法创建的Bean,需要在Bean的class属性中指定拥有该工厂的方法的类,同时需要在bean的factory-method属性里指定工厂方法的名称.最后,使用<constructor-arg>元素为该方法传递方法参数. 示例: 第一步:创建一个java project,导入包: 第二步:创建c

Spring中Bean的配置方式之通过工厂方法

通过调用静态工厂方法创建Bean 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节. 要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数. 相关代码: Car.java private String brand